home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / doc / sm3doc.ascii < prev    next >
Encoding:
Text File  |  1996-05-05  |  217.2 KB  |  6,018 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.                         Using the EXODUS Storage Manager V3.1
  29.                            (Last revision: November, 1993)
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.           ____________________
  53.              The  Exodus  software  was  developed  primarily  with   funds
  54.           provided  by  by  the  Defense  Advanced Research Projects Agency
  55.           under contracts N00014-85-K-0788, N00014-88-K-0303,  and  DAABO7-
  56.           92-C-Q508  and  monitored  by  the  US  Army Research Laboratory.
  57.           Additional support was provided  by  Texas  Instruments,  Digital
  58.           Equipment Corporation, and Apple Computer.
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.           1.  INTRODUCTION
  75.  
  76.           The EXODUS Storage Manager is a multi-user object storage  system
  77.           supporting  versions,  indexes, single-site transactions, distri-
  78.           buted transactions, concurrency control, and recovery. This docu-
  79.           ment  provides  information about using version 3.1 of the EXODUS
  80.           Storage  Manager.   Information  about  installing  the   Storage
  81.           Manager  can  be found in the EXODUS Storage Manager Installation
  82.           Manual.  Section 2 gives an overview of  the  system.  Section  3
  83.           discusses  configuration  facilities.  Section  4  describes,  in
  84.           detail, the Storage Manager's application  interface.  Section  5
  85.           describes  how to use the Storage Manager server. Appendices pro-
  86.           vide more details on certain aspects of the system.  A  table  of
  87.           contents is located at the end of the document.
  88.  
  89.           2.  OVERVIEW OF THE EXODUS STORAGE MANAGER
  90.  
  91.           This section, an executive summary, briefly describes the  archi-
  92.           tecture  of  the  Storage  Manager  and  gives an overview of the
  93.           facilities provided to applications,
  94.  
  95.           Version 3.1 of the Storage Manager runs on the  following  archi-
  96.           tectures:  Sun  4  (Sparc)  (under  SunOS  4.1.[23]),  DecStation
  97.           3100/5000 (MIPS) (under Ultrix 4.2),  and  HP  720  (under  HP-UX
  98.           A.08.07).   The  Storage  Manager  is written in C++ and had been
  99.           checked for compilation under the GNU C++ compiler (g++), version
  100.           2.3.3 and 2.4.5.
  101.  
  102.           2.1.  Architecture
  103.  
  104.           The EXODUS Storage Manager has a client-server  architecture.  An
  105.           application program that uses the Storage Manager may reside on a
  106.           machine different from the  machine  or  machines  on  which  the
  107.           Storage  Manager server or servers run.  We use the term applica-
  108.           tion to refer to programs that use the  Storage  Manager  through
  109.           the  client  programming interface described in Section 4. We use
  110.           the term client library, or  client,  to  refer  to  the  Storage
  111.           Manager  code and data structures that are linked into the appli-
  112.           cation program to support the client programming  interface.  The
  113.           client allows applications to use the facilities described in the
  114.           next sub-section. Each client has its own buffer pool for caching
  115.           data. The client library connects to one or more server processes
  116.           and communicates with them  using  a  remote-procedure-call-style
  117.           mechanism that runs over TCP.
  118.  
  119.           The Storage Manager server is a multi-threaded process  providing
  120.           asynchronous  I/O,  file,  transaction,  concurrency control, and
  121.           recovery services to multiple clients. The server stores all data
  122.           on  volumes,  which are either Unix files or raw disk partitions.
  123.           The server is more completely described in Section 5 and  in  the
  124.           EXODUS Storage Manager Architecture Overview [exoArch].
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.           2.2.  Facilities
  141.  
  142.           The EXODUS Storage Manager provides  objects  for  storing  data,
  143.           versions  of  objects,  files  for  grouping related objects, and
  144.           indexes for  supporting  efficient  object  access.  The  Storage
  145.           Manager also provides volumes, transactions, concurrency control,
  146.           recovery,  and  configuration  options.   These  facilities   are
  147.           presented  briefly  in  this section, and more information can be
  148.           found in later sections of the document.
  149.  
  150.           2.2.1.  Objects
  151.  
  152.           An object is an uninterpreted container of bytes, which can range
  153.           in  size  from  a  few  bytes to a little less than the size of a
  154.           disk.  Internally, the Storage Manager distinguishes two types of
  155.           objects.   There are small objects, which are objects that fit on
  156.           a single disk page, and large objects, which are objects that  do
  157.           not  fit  on  a  single  disk page.  Support is also provided for
  158.           creating and  manipulating  versions  of  both  small  and  large
  159.           objects.   To provide a uniform function call interface, the dis-
  160.           tinction between small, large, and versioned  objects  is  hidden
  161.           from  applications.  Applications are unaware of whether they are
  162.           dealing with a small or large  object,  and  the  same  interface
  163.           functions  are  called  to  manipulate either type of object.  To
  164.           simplify the task of manipulating very large objects, the Storage
  165.           Manager   provides   flexible   buffer   management  that  allows
  166.           variable-length pieces of large objects to be  buffered  contigu-
  167.           ously in the client buffer pool.
  168.  
  169.           Objects have object identifiers.   The  object  identifier  of  a
  170.           small  object  points  directly  to the object on disk, while the
  171.           object identifier of a large object  points  to  a  large  object
  172.           header.  The  header  of  a  large object serves as the root of a
  173.           B[+]tree index structure that is used to access the object's data
  174.           [Care86, Care89]. For space efficiency, a large object header can
  175.           share a disk page with  small  objects  and  other  large  object
  176.           headers.   The  data  pages  and the pages that make up the index
  177.           structure of a large object are  not  shared,  however.   When  a
  178.           small  object grows to the point where it can no longer be stored
  179.           on a single page, the Storage Manager automatically  converts  it
  180.           to  a large object, leaving the new header in place of the origi-
  181.           nal object.
  182.  
  183.           The  Storage  Manager  provides  functions  to  read,  overwrite,
  184.           insert, delete, and append to an object. Read requests specify an
  185.           object identifier and a range of bytes. The desired data is  read
  186.           into  a  contiguous  region in the client buffer pool (even if is
  187.           distributed over several disk pages), and a pointer to  the  data
  188.           is  returned  to  the  caller.  The  overwrite  function uses the
  189.           pointer set up by a read request, and overwrites  a  subrange  of
  190.           the  data.   The  insert  and  delete  functions allow data to be
  191.           inserted into and deleted  from  objects  at  arbitrary  offsets,
  192.  
  193.  
  194.  
  195.                                           2
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.           while  the  append function allows data to be appended to the end
  207.           of an object. As mentioned earlier, large objects are represented
  208.           using  a  B[+]tree index structure. This ensures that each of the
  209.           above operations can be executed efficiently on large objects.
  210.  
  211.           2.2.2.  Versions
  212.  
  213.           A version of an object is another object that  appears  to  be  a
  214.           copy  of  the  original  object. A version of a small object is a
  215.           copy of the original object. A version of a large  object  is  an
  216.           object  header  with  a  pointer into the original object's data,
  217.           until either the version or the original object is updated.  When
  218.           the large object version is updated, the affected portions of the
  219.           original object are copied to  prevent the original  object  from
  220.           being  affected by the update [Care89]. Although the version sup-
  221.           port described here is primitive,  essentially  providing  "copy-
  222.           on-write"  objects, it has been purposefully designed that way so
  223.           that a variety of application-specific versioning schemes can  be
  224.           implemented on top of the Storage Manager.
  225.  
  226.           2.2.3.  Files
  227.  
  228.           Objects are allocated in files, which are collections of  related
  229.           objects.  Files have three uses.
  230.  
  231.           First, files are used for clustering objects.  The objects  in  a
  232.           file  are  stored on disk pages allocated solely to that file, so
  233.           files provide a way to physically co-locate  related  objects  on
  234.           the disk.
  235.  
  236.           Second, the Storage Manager provides an efficient way to scan the
  237.           objects in a file, visiting each object exactly once.
  238.  
  239.           Third, the Storage Manager  offers  an  efficient  mechanism  for
  240.           loading the objects into a file in bulk.
  241.  
  242.           2.2.4.  Indexes
  243.  
  244.           The Storage Manager provides B[+]tree indexes and linear  hashing
  245.           indexes.   Index  keys  can  be any basic C language data type or
  246.           strings. Values can be any type of fixed length.
  247.  
  248.           2.2.5.  Volumes
  249.  
  250.           User data and Storage Manager meta-data (objects, files, indexes,
  251.           and  logs)  are  stored  on  volumes. A volume represents a disk,
  252.           although in fact it may be a Unix raw disk partition  or  a  Unix
  253.           file.
  254.  
  255.           Volumes can be temporary, which means that data  stored  on  them
  256.           are  not  logged, and they do not persist from one transaction to
  257.           the next.  Temporary volumes are meant to  provide  fast  storage
  258.  
  259.  
  260.  
  261.                                           3
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.           for temporary data.
  273.  
  274.           2.2.6.  Transactions
  275.  
  276.           A transaction is a set  of  operations  on  objects,  files,  and
  277.           indexes.  Transactions  are  either committed or aborted. Updates
  278.           made by committed transactions are guaranteed to be reflected  on
  279.           stable  storage,  even  in  the  event  of  software or processor
  280.           failure. Updates made by aborted transactions are  not  reflected
  281.           on stable storage.
  282.  
  283.           Transactions that use data on more than one server are  committed
  284.           using a distributed two-phase commit protocol [Moha83].
  285.  
  286.           2.2.7.  Concurrency Control
  287.  
  288.           Concurrency control allow multiple client applications safely  to
  289.           use  data  simultaneously.  Concurrency  control  is based on the
  290.           standard  hierarchical  two-phase  locking   protocol   providing
  291.           degree-three consistency (see [Gray78, Gray88]). The lock hierar-
  292.           chy contains two granularities: file-level, and page-level. Lock-
  293.           ing for index operations is performed with a non-two-phase proto-
  294.           col, which allows multiple clients to read and  update  the  same
  295.           index.
  296.  
  297.           Deadlocks involving more than one  server  are  resolved  through
  298.           timeouts.
  299.  
  300.           2.2.8.  Recovery
  301.  
  302.           The Storage Manager recovers from software, operating system, and
  303.           CPU  failure  by  restoring data to a state in which all transac-
  304.           tions have been  committed  or  aborted.   After  an  application
  305.           fails,  the  transaction  it is running is aborted by the servers
  306.           that cooperated in the transaction. After a server fails  and  is
  307.           restarted,  updates  made by committed transactions are restored,
  308.           and updates by transactions in progress at the  time  of  failure
  309.           are undone. Recovery from media (disk) failure is not supported.
  310.  
  311.           2.2.9.  Configuration Options
  312.  
  313.           The Storage Manager client library and servers have configuration
  314.           options,  which  can  be set by users. These options control such
  315.           things as parameters that affect performance and memory use, for-
  316.           mats  of  volumes and logs, the choice of servers to be contacted
  317.           by clients, and path names of installed executable files.
  318.  
  319.           2.3.  Illustration of Using the Storage Manager
  320.  
  321.           The purpose of this section is to give the reader  a  context  in
  322.           which  to  read  the  rest of this document.  This section illus-
  323.           trates a way to get started using the Storage Manager.  There are
  324.  
  325.  
  326.  
  327.                                           4
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.           many  ways  to  install,  configure, and use the Storage Manager;
  339.           only the simplest way is illustrated here.
  340.  
  341.           This section uses an  example  application,  "producer-consumer".
  342.           The  source  code for the application programs is included in the
  343.           Storage Manager software release, along with other example appli-
  344.           cations.
  345.  
  346.           The producer program generates a series of transactions, each  of
  347.           which  creates an object. The consumer program generates a series
  348.           of transactions, each of which reads an object and  destroys  it.
  349.           These  programs  were selected because they are relatively small,
  350.           demonstrate the use of transactions, and show how to  respond  to
  351.           server-initiated transaction failures and server failures.
  352.  
  353.           The remainder of  this  section  gives  specific  directions  for
  354.           starting  a  server  and  running  the example program.  Detailed
  355.           explanations of the steps are not given here; all the details are
  356.           given elsewhere in this document.
  357.  
  358.           Installing the storage manager is akin to installing an operating
  359.           system or a remote file system (but it's much simpler).  You need
  360.           to:
  361.  
  362.            (1)   install  the  system's  executable  code,  libraries,  and
  363.                  include files;
  364.  
  365.            (2)   prepare your disks for use;
  366.  
  367.            (3)   configure your server so that it will use your disks,  and
  368.                  so that it is otherwise tailored for your use;
  369.  
  370.            (4)   compile and link your  application  programs  to  use  the
  371.                  installed system;
  372.  
  373.            (5)   configure your application programs' environment, run  the
  374.                  programs, and
  375.  
  376.            (6)   when you are finished, shut the system down.
  377.  
  378.           2.3.1.  Files Needed
  379.  
  380.           The following files are needed to use the Storage Manager:
  381.  
  382.            (1)   libsm_client.a, the Storage Manager client library,
  383.  
  384.            (2)   sm_client.h, the include file containing  declarations  of
  385.                  key data structures and constants,
  386.  
  387.            (3)   sm_server, the executable file for the server  portion  of
  388.                  the Storage Manager,
  389.  
  390.  
  391.  
  392.  
  393.                                           5
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.            (4)   diskrw, the executable file for  the  disk  I/O  processes
  405.                  used by the server process,
  406.  
  407.            (5)   formatvol, and a utility program for formatting volumes,
  408.  
  409.            (6)   .sm_config, configuration files for  a  server,  the  for-
  410.                  matter,  and  the  application programs. One configuration
  411.                  file can be used for all programs,  but  it  is  sometimes
  412.                  easier  to use configuration file for servers and the for-
  413.                  matter, and another for applications.
  414.  
  415.           These files can be installed anywhere; for the  purpose  of  this
  416.           section,  we  assume  that  they  are  all installed in your home
  417.           directory, along with your application programs.  (See the EXODUS
  418.           Storage  Manager  Installation  Manual  to  find the files in the
  419.           Storage Manager software release.)
  420.  
  421.           2.3.2.  Preparing Your Disks
  422.  
  423.           The producer and consumer programs use a volume for storing their
  424.           objects  with  a single server, and the server uses a log volume.
  425.           The formatvol program is used to  format  a  volume  for  use  as
  426.           either  a  data volume or a log volume.  If you plan to use a raw
  427.           disk partition for either volume, ask your  system  administrator
  428.           for information on how to set up the device.
  429.  
  430.           The formats of the volumes must be described in the configuration
  431.           file that formatvol reads.  In the directory in which you plan to
  432.           run formatvol, create a file called .sm_config that  looks  some-
  433.           thing like this, with the appropriate substitutions:
  434.  
  435.  
  436.               formatvol*logformat:  /path/to/logfile: 9000: 1: 1: 1000: 8
  437.               formatvol*dataformat: /path/to/datafile: 8000: 1: 1: 300
  438.  
  439.  
  440.  
  441.           Substitute the pathnames for files that you want to use for  your
  442.           log  volume  and  data volume.  With the options given above, the
  443.           log volume will be given a volume identifier of  9000,  and  will
  444.           consist  of  1 cylinder of 1 track each, with 1000 blocks on each
  445.           track, hence, 1000 blocks will be on the  log.   The  log  volume
  446.           will  use  8  Kbyte  log  pages.  The data volume will be given a
  447.           volume identifier of 8000, and will consist of 1  cylinder  of  1
  448.           track each, with 300 blocks on each track, hence, 300 blocks will
  449.           be on the data volume.
  450.  
  451.           Now, run the formatter on volumes 9000 and 8000:
  452.  
  453.               formatvol -vol 9000 -vol 8000
  454.  
  455.  
  456.  
  457.  
  458.  
  459.                                           6
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.           If you would like to see the information written on the  volumes'
  471.           headers, do this:
  472.  
  473.               formatvol -dis 9000 -dis 8000
  474.  
  475.  
  476.           The formatter prints:
  477.  
  478.           VOLID 9000, version 3, is a LOG volume
  479.              BLOCK SIZES: 8 K slotted, 8 K lg data,  8 K lg hdr
  480.                      8 K btree, 8 K idesc
  481.              LAYOUT: 1000 blk/trk; 1 trk/cyl; 1 cyl
  482.                      1000 total blocks of 8 KB for 8192.000 KB
  483.              FREE: 0 free, 1000 used
  484.              BITMAP: 1 blk each, freemap @ 2, slotmap @ 4, filemap @ 5
  485.              UNIQUE: start @ 3
  486.              LOG: start @ 7, ctl blk @ 6, blk sz 8 K, #blks 993
  487.                           end of log @ dismount: LSN w=0.o=0, LRC w=0.c=1
  488.           VOLID 8000, version 3, is a DATA volume
  489.              BLOCK SIZES: 8 K slotted, 8 K lg data,  8 K lg hdr
  490.                      8 K btree, 8 K idesc
  491.              LAYOUT: 300 blk/trk; 1 trk/cyl; 1 cyl
  492.                      300 total blocks of 8 KB for 2457.600 KB
  493.              FREE: 294 free, 6 used
  494.              BITMAP: 1 blk each, freemap @ 2, slotmap @ 4, filemap @ 5
  495.              UNIQUE: start @ 3
  496.  
  497.  
  498.  
  499.           Now that you have formatted a log volume and a data  volume,  you
  500.           are ready to start a server.
  501.  
  502.           2.3.3.  Configuring a Server
  503.  
  504.           Before you start a server, you need to create  its  configuration
  505.           file.   In  the  directory in which you expect to run the server,
  506.           create a file called .sm_config that looks something  like  this,
  507.           with  the  appropriate  substitutions  (in  particular,  for each
  508.           occurrence of /path/to below):
  509.  
  510.  
  511.               server*bufpages:    500
  512.               # Portname need not be identical to log volume id.
  513.               # This is just a convenience.
  514.               server*portname:    9000
  515.               server*diskproc:    /path/to/diskrw
  516.               server*logformat:    /path/to/logfile: 9000: 1: 1: 1000: 8
  517.               server*dataformat:   /path/to/datafile: 8000: 1: 1: 500
  518.               server*logvolume:    9000
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.                                           7
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.           If the same configuration file is to be used  for  the  formatter
  537.           and  the  server, the format options can be made to be recognized
  538.           by both:
  539.  
  540.  
  541.               [sf]*[rl].logformat: /path/to/logfile: 9000: 1: 1: 1000: 8
  542.               [sf]*[rl].dataformat:/path/to/datafile: 8000: 1: 1: 500
  543.  
  544.  
  545.  
  546.           Now you can start the server.  Open a window in which to run  the
  547.           server,  and, in the directory containing the server and its con-
  548.           figuration file, start the server:
  549.  
  550.               sm_server
  551.  
  552.           The server is started on a newly  formatted  log  volume,  so  it
  553.           automatically regenerates the log. The server prints
  554.  
  555.               Server is ready for requests.
  556.  
  557.           when it can serve applications.
  558.  
  559.           2.3.4.  Compiling and Linking Your Application
  560.  
  561.           An application program must include the header file  sm_client.h,
  562.           which,  in  turn  includes  <stdio.h>, <setjmp.h>, <sys/types.h>,
  563.           <netinet/in.h>.  Applications can be compiled with  a  C  or  C++
  564.           compiler.
  565.  
  566.           The client library is compiled with C++, so client programs  must
  567.           be  linked  with  a C++ compiler.  See the EXODUS Storage Manager
  568.           Installation Manual for more information.
  569.  
  570.           2.3.5.  Configuring and Running Your Application
  571.  
  572.           The programs need configuration options  to  determine  where  to
  573.           find  the  server  that manages the data volumes they use, and to
  574.           determine the sizes of the buffer pools they will  use.   In  the
  575.           directory  in  which  you expect to run the application programs,
  576.           Create a file called .sm_config that looks something  like  this,
  577.           with the appropriate substitutions:
  578.  
  579.  
  580.               # both producer and consumer will use
  581.               # 250 page buffer pools:
  582.               client*bufpages:    250
  583.               # substitute the name or Internet address
  584.               # of the host on which the server runs:
  585.               client*mount:    8000   9000@serverhost
  586.  
  587.  
  588.  
  589.  
  590.  
  591.                                           8
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.           Now you can run the producer and the consumer.  It is easiest  to
  603.           create  a  window  in which to run each program.  The produce and
  604.           consumer programs use the environment variable EVOLID  to  deter-
  605.           mine the what volume to use.  EVOLID must be set in each window.
  606.  
  607.           In window P:
  608.  
  609.               # producer <name> <#objects> <object size>
  610.               setenv EVOLID 8000
  611.               producer P 100 1000
  612.  
  613.           In window C:
  614.  
  615.  
  616.               # consumer <name> <#objects>
  617.               setenv EVOLID 8000
  618.               consumer C 100
  619.  
  620.  
  621.           The producer creates "#objects" objects and writes "name" in each
  622.           one.  The "object size" argument is the size of each object.  The
  623.           consumer reads and destroys "#objects"  objects.  It  prints  the
  624.           sizes  of  the  objects and their names.  The "name" given to the
  625.           consumer program is immaterial, but is helpful  for  reading  the
  626.           output when running more than one consumer.
  627.  
  628.           The two programs use a single root entry and a single file on the
  629.           given  volume.  When a consumer has consumed the last object in a
  630.           file, it destroys the file  and  removes  the  root  entry.  Each
  631.           object  is  produced  or consumed in a separate transaction. When
  632.           both a producer and consumer are running concurrently,  deadlocks
  633.           occur  periodically,  since both are reading and writing the same
  634.           file. When a deadlock occurs, the offending  program  aborts  its
  635.           transaction  and tries again. Multiple producer and consumer pro-
  636.           grams may be started. If the server fails or shuts down, the pro-
  637.           ducer  and  consumer  programs  attempt  to  reconnect every five
  638.           seconds, and when successful, they continue transaction  process-
  639.           ing.
  640.  
  641.           2.3.6.  Shutting Down the Server
  642.  
  643.           In the window in which the server runs, type the command:
  644.  
  645.               shutdown
  646.  
  647.  
  648.           The server prints various messages, among them
  649.  
  650.  
  651.               Clean shutdown: no recovery required on any volumes.
  652.               All disk processes  killed.
  653.  
  654.  
  655.  
  656.  
  657.                                           9
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668.           when recovery is not required.
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.                                          10
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734.           3.  CONFIGURATION OPTIONS AND CONFIGURATION FILES
  735.  
  736.           The client library, servers, and administrative programs use con-
  737.           figuration  options.  All the options have a string name, a type,
  738.           a set of possible values, a default value, and a  current  value.
  739.           Client  options  can be set by a call to an application interface
  740.           function or by a line in a configuration file. Server options can
  741.           be  set  on  the command line or by a line in the server's confi-
  742.           guration file.
  743.  
  744.           Configuration files are Unix files, and are similar in format  to
  745.           the  X  Window system's resource files. Each line in a configura-
  746.           tion file is an option command or a comment.
  747.  
  748.           A comment is a line that begins with "#" or with "!".
  749.  
  750.           An option command is a  line  containing  an  option  descriptor,
  751.           white  space,  and a string representing a value to assign to the
  752.           option. An option descriptor consists of an  option  prefix  fol-
  753.           lowed immediately by an option name and a ":".
  754.  
  755.           The option prefix specifies the type and name of the  program  or
  756.           programs  for  which the option is to be set. The program type is
  757.           one of "client", "server", and "formatvol". The program  name  is
  758.           usually the file name of the program, without its path (an appli-
  759.           cation program can override this).  The program type and  program
  760.           name  are  separated  by  ".".  For  example, the complete option
  761.           descriptor for the option "bufpages" on the server named  serverA
  762.           is server.serverA.bufpages:.
  763.  
  764.           Wild card characters are allowed in the program  type  and  name.
  765.           The  character  "*" represents any portion of the prefix. The "?"
  766.           character represents any program type or any  program  name.  The
  767.           expressions  describing the program type and the program name are
  768.           parsed by a regular expression handler,  so  complex  expressions
  769.           can be used.  See the manual page for regex(3).
  770.  
  771.           The names of options can be abbreviated, as long as the abbrevia-
  772.           tion unambiguously identifies a single option. (This is also true
  773.           for options appearing on command lines.)  Program types and names
  774.           may  not  be  abbreviated. Option name, program type, and program
  775.           name matches are case-sensitive.
  776.  
  777.           Configuration options of type Boolean can be set with the Boolean
  778.           values  TRUE or FALSE, or with the strings "yes", "true", "no" or
  779.           "false". The  strings  may  be  abbreviated  and  are  not  case-
  780.           sensitive.
  781.  
  782.           Each setting of an option overrides any previous value  for  that
  783.           option.
  784.  
  785.  
  786.  
  787.  
  788.  
  789.                                          11
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800.           Below, excerpts from configuration files illustrate ways  to  use
  801.           the options.
  802.  
  803.  
  804.               # log volumes for two servers, whose executable
  805.               # file names are serverA and serverB
  806.               server.serverA.logvolume:               1000
  807.               server.serverB.logvolume:               2000
  808.  
  809.  
  810.  
  811.  
  812.               # turn off progress printing for all servers
  813.               server*progress:                                no
  814.               # or
  815.               server.?.progress:                              no
  816.  
  817.  
  818.  
  819.  
  820.               ! all servers and clients have a 1000 page buffer pool
  821.               *bufpages:                                      1000
  822.               # The application foo uses a 500 page buffer pool.
  823.               # (overriding the value of 1000, above)
  824.               client.foo.bufpages:                    500
  825.               # Applications beginning with the letter g use 400 pages
  826.               client.g*.bufpages:                             400
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.                                          12
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.           4.  THE STORAGE MANAGER APPLICATION INTERFACE
  867.  
  868.           The Storage Manager's application interface consists of a set  of
  869.           functions,  macros,  and variables.  The Storage Manager software
  870.           release contains the header file sm_client.h, in which are  found
  871.           the  definitions  for  the  macros  and types that appear in this
  872.           document.  Function prototypes for the the Storage Manager  func-
  873.           tions  are  also found in sm_client.h.  By convention, words that
  874.           appear capitalized in the text are either C-preprocessor  macros,
  875.           or C- or C++- defined types, Functions definitions appear in bold
  876.           face in the text.  The rest of this section is divided into  sub-
  877.           sections  describing error handling, initialization and shutdown,
  878.           transactions, buffer management, operations  on  objects,  opera-
  879.           tions  on  versions,  operations on files, operations on indexes,
  880.           miscellaneous macros, and administrative functions.
  881.  
  882.           4.1.  Handling Errors
  883.  
  884.           Error handling is important to  users  wishing  to  write  robust
  885.           client  applications.  We  discuss  it  first, since most Storage
  886.           Manager functions return error codes. Although this issue is com-
  887.           plex,  some of the burden is lightened by the recovery facilities
  888.           of the Storage Manager. In this section we focus on  error  codes
  889.           and error messages.
  890.  
  891.           Almost all Storage Manager functions have integer  return  codes.
  892.           All  functions  (except  those  used  in printing error messages)
  893.           return either esmNOERROR (zero),  which  represents  success,  or
  894.           esmFAILURE  (negative  one),  which  represents an error. When an
  895.           error occurs, the global  variable  sm_errno  contains  an  error
  896.           code.  A  small  positive error code is an error code returned by
  897.           Unix, as defined in <errno.h>. An error code greater than  65,536
  898.           is  an  error  returned  by  the  Storage  Manager, as defined in
  899.           sm_client.h.  The Storage Manager error codes have symbolic names
  900.           (C  preprocessor  macros)  that  begin  with  esm.   The value of
  901.           sm_errno is not defined when the function returns esmNOERROR.
  902.  
  903.           Information about error codes can be obtained from the  functions
  904.           sm_Error( ), and sm_ErrorId( ), which are discussed below.
  905.  
  906.           Some errors cause a message to be printed to the  file  addressed
  907.           by  sm_ErrorStream.   By default, this file is the standard error
  908.           file, stderr, as defined in <stdio.h>, but  the  application  can
  909.           change it any time after the Storage Manager is initialized.
  910.  
  911.           Errors differ in severity and have different side  effects.   The
  912.           most  severe  errors  are fatal and cause the application to exit
  913.           (the client library calls exit(3)).  When the application  exits,
  914.           the  servers  abort  the transaction, if a transaction is active.
  915.           Fatal errors are caused by  internal  software  problems  in  the
  916.           Storage  Manager. An example of a fatal error is esmMALLOCFAILED,
  917.           which occurs when the entire data segment has been  allocated  by
  918.  
  919.  
  920.  
  921.                                          13
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.  
  932.           the  application and client library, and the Storage Manager can-
  933.           not proceed.
  934.  
  935.           Less severe errors cause the transaction to be aborted, but leave
  936.           the  application  running.   When this happens, sm_errno is given
  937.           the value esmTRANSABORTED, and the client library also  sets  the
  938.           global  variable sm_reason.  The range of values for sm_reason is
  939.           the same as the range of values  for  sm_errno.   (The  value  of
  940.           sm_reason is meaningful only if sm_errno has the value esmTRANSA-
  941.           BORTED, and it is unpredictable and meaningless otherwise.)  When
  942.           the server or the client library aborts a transaction and returns
  943.           esmTRANSABORTED to the application, the transaction is only  par-
  944.           tially aborted.  The application must complete the termination of
  945.           the transaction by calling sm_AbortTransaction( )  (described  in
  946.           the Section 4.3.3, Transaction Operations).
  947.  
  948.           Less severe errors are generated by incorrect arguments to client
  949.           interface  functions  or  the  lack  of resources, such as buffer
  950.           space.  The application can correct the  problem  and  retry  the
  951.           operation without aborting the transaction.
  952.  
  953.           Finally, some error codes indicate conditions that are not errors
  954.           at  all,  such  as  esmEMPTYFILE, which is returned when an empty
  955.           file is read.
  956.  
  957.           The following two functions can be used to print more information
  958.           about the error.
  959.  
  960.  
  961.           char *sm_Error (errorCode)
  962.           int              errorCode;             /* error code returned by an sm function /*
  963.  
  964.  
  965.           char *sm_ErrorId (errorCode)
  966.           int              errorCode;             /* error code returned by an sm function /*
  967.  
  968.  
  969.           These are the only Storage Manager functions that do  not  return
  970.           an  integer.  When  a  client  library function returns an error,
  971.           sm_Error( ) can be called by the application to get a string that
  972.           provides  a  brief  description  of  the  error. It also provides
  973.           descriptions of Unix  error  codes.   Sm_ErrorId( )  is  used  to
  974.           return  the string representation of the error code. For example,
  975.           the call sm_ErrorId(esmBADOID) returns  the  string  "esmBADOID",
  976.           and  the  call  sm_Error(esmBADOID)  returns  the string "invalid
  977.           object id."
  978.  
  979.           If the client is disconnected from a server (by a  server  crash,
  980.           network  failure,  etc.) the client library tries to reconnect to
  981.           the server the next time it issues a request to the  server.   If
  982.           the  server  in  question  is  not available, the Storage Manager
  983.           returns an error such as esmSERVERDIED or a Unix  error  such  as
  984.  
  985.  
  986.  
  987.                                          14
  988.  
  989.  
  990.  
  991.  
  992.  
  993.  
  994.  
  995.  
  996.  
  997.  
  998.           ECONNREFUSED.   While  the  server  in question is doing recovery
  999.           after  a  restart,  esmTRANSDISABLED  is  returned.   The  server
  1000.           responds to requests when recovery is completed.
  1001.  
  1002.           4.2.  Initialization and Shutdown Operations
  1003.  
  1004.           Initialization and shutdown functions are used at  the  beginning
  1005.           and end of an application program, but most of them can be called
  1006.           at any time. The pertinent functions  are  sm_SetClientOption( ),
  1007.           sm_GetClientOption( ),                    sm_ParseCommandLine( ),
  1008.           sm_ReadConfigFile( ), sm_Initialize( ), and sm_ShutDown( ).
  1009.  
  1010.           Before   initializing   the   Storage   Manager    client    with
  1011.           sm_Initialize( ),  a  number of client configuration options must
  1012.           be set by the application.  Options can be set through  calls  to
  1013.           sm_SetClientOption( ),         sm_ParseCommandLine( ),         or
  1014.           sm_ReadConfigFile( ).  These options are summarized in  Table  1.
  1015.           See Section 3 for information that applies to all options.
  1016.  
  1017.  
  1018.           ____________________________________________________________________________________
  1019.               Option      Option        Possible        Default              Option
  1020.                Name        Type          Values          Values           Description
  1021.           ____________________________________________________________________________________
  1022.            bufpages       int       > 4                 none       # pages in the buffer pool
  1023.            groups         int       > 3                 20         # buffer groups
  1024.            userdesc       int       > 0                 2000       # user descriptors
  1025.            mount          string    volid port@host     none       where to find server
  1026.                                                                    for this volume
  1027.            lognewpages    Boolean   yes,no,true,false   no/false   client logs new pages
  1028.            deallocpages   Boolean   yes,no,true,false   yes/true   removes empty pages
  1029.            pagelock       string    SH,EX               SH         default lock for pages
  1030.            traceflags     int       >= 0                0          set tracing flags
  1031.            locktimeout    int       >= 0                30         # 10-second intervals
  1032.                                                                    willing to await a lock
  1033.           ____________________________________________________________________________________
  1034.           |
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.                         |
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.                                   |
  1063.  
  1064.  
  1065.  
  1066.  
  1067.  
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.                                                       |
  1077.  
  1078.  
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.                                                                  |
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096.  
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.                                                                                               |
  1105.  
  1106.  
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.                               Table 1: Client Options
  1122.  
  1123.  
  1124.           The "bufpages" option sets the size of the client buffer pool  in
  1125.           8  Kbyte pages (or n byte pages, for n=MIN_PAGESIZE; MIN_PAGESIZE
  1126.           is defined in  sm_client.h).   See  Section  4.11.3,  Tuning  the
  1127.           Application for more information about setting this option.
  1128.  
  1129.           The "groups" option sets the limit on the number of buffer groups
  1130.           that can be opened at once. The default value is 20.  See Section
  1131.           4.6, Buffer Operations, for more information about buffer groups.
  1132.  
  1133.  
  1134.  
  1135.  
  1136.  
  1137.  
  1138.                                          15
  1139.  
  1140.  
  1141.  
  1142.  
  1143.  
  1144.  
  1145.  
  1146.  
  1147.  
  1148.  
  1149.           The "userdescs" option sets the limit on the number of open  user
  1150.           descriptors.  The number of user descriptors should be set to the
  1151.           maximum  number  of  simultaneous  object  references  that   are
  1152.           expected  by  the application program. The default value is 2000.
  1153.           See Section 4.7, Operations  on  Objects,  for  more  information
  1154.           about user descriptors.
  1155.  
  1156.           The "lognewpages" option, if "yes", causes the client to generate
  1157.           log  pages  for  newly  allocated  pages, and if "no", causes the
  1158.           server to generate the log pages.  Setting this  option  to  "no"
  1159.           results  in  fewer  log  records  shipped  to servers and usually
  1160.           lowers  log  space  requirements  for  transactions  that  create
  1161.           objects.  With  rare  patterns  of  use, setting "lognewpages" to
  1162.           "yes" results in better performance: if the  objects  that  cause
  1163.           new  pages  to be allocated are small, and if enough work is done
  1164.           between object-creation operations to cause the  newly  allocated
  1165.           pages  to  be  swapped,  the preferred value for "lognewpages" is
  1166.           "yes".  In general, it is difficult to predict which objects will
  1167.           be be created on newly allocated pages.  The "lognewpages" option
  1168.           may be set only when a transaction is not active.
  1169.  
  1170.           The "deallocpages" option, if "yes", causes the client to deallo-
  1171.           cate pages that become empty after objects are destroyed.  If the
  1172.           option's value is "no", these pages remain in the  file,  and  do
  1173.           not  get used again unless an appropriate near-hint is given when
  1174.           an object is subsequently created.  Under most circumstances, the
  1175.           preferred  value  of  "deallocpages"  is  "yes".   If objects are
  1176.           created and destroyed in a LIFO fashion, and if the near-hint for
  1177.           object creation is NEAR_LAST, the preferred  value is "no".
  1178.  
  1179.           The "pagelock" option changes the default lock  mode  for  pages.
  1180.           See  the Section 4.2, Initialization and Shutdown Operations, and
  1181.           Appendix A, Locking Protocol for Storage Manager  Operations  for
  1182.           information about using options.
  1183.  
  1184.           The "traceflags" option is used to turn on tracing, and  is  only
  1185.           available  in  a  Storage Manager that was compiled with -DDEBUG.
  1186.           The "traceflags" option takes effect immediately and can  be  set
  1187.           at any time.
  1188.  
  1189.           The "mount" options indicate the locations of  the  volumes  that
  1190.           the  applications  use.  The "mount" option may be used more than
  1191.           once, to add new volumes to the client library's  set  of  usable
  1192.           volumes, or to change the location of a volume.  The option value
  1193.           consists of a volume's integer identifier, an  Internet  address,
  1194.           and  a  port  at  which  can  be  found a server that manages the
  1195.           volume.  The Internet addresses and port have format port @ host,
  1196.           where  both  the  port  and  the host can be numeric or symbolic.
  1197.           Symbolic port names must be found in the services  database  used
  1198.           by getservbyname(3n), and symbolic host names must be in the host
  1199.           name database used by gethostbyname(3n).  The  following  example
  1200.           shows  three  values  for  the "mount" option that accomplish the
  1201.  
  1202.  
  1203.  
  1204.                                          16
  1205.  
  1206.  
  1207.  
  1208.  
  1209.  
  1210.  
  1211.  
  1212.  
  1213.  
  1214.  
  1215.           same thing in three ways.  The volume  1000  is  managed  by  the
  1216.           server  listening  on  port 1152 (which is called "bounty" in the
  1217.           /etc/services database) on  the  local  machine,  whose  Internet
  1218.           address  is  128.105.2.153,  also known as "pitcairn.isle.edu" to
  1219.           the host-name server.
  1220.  
  1221.                       1000 1152@128.105.2.153
  1222.                       1000 bounty@pitcairn.isle.edu
  1223.                       1000 1152@pitcairn.isle.edu.
  1224.               and
  1225.                       1000 bounty@128.105.2.153
  1226.  
  1227.  
  1228.           The host name localhost does not work if you  are  using  distri-
  1229.           buted transactions (multiple cooperating servers).
  1230.  
  1231.           Volume identifiers must identify  volumes  unambiguously,  across
  1232.           all servers.
  1233.  
  1234.           For each application or client, all the host  names  used  for  a
  1235.           given  server  must  resolve to the same Internet address.  Using
  1236.           the  above  example,  this   means   that   "128.105.2.153"   and
  1237.           "pitcairn.isle.edu"   are  interchangeable.   "Localhost",  which
  1238.           resolves to the Internet address 127.0.0.1, is  not  interchange-
  1239.           able  with "128.105.2.153" or "pitcairn.isle.edu", even though it
  1240.           addresses  the  same  machine  when   used   by   a   client   on
  1241.           "pitcairn.isle.edu".
  1242.  
  1243.           It is acceptable to  use  two  different  servers  running  on  a
  1244.           machine, by addressing them at different ports.  This means that
  1245.  
  1246.                       1000 1151@pitcairn.isle.edu
  1247.               and
  1248.                       2000 1152@pitcairn.isle.edu
  1249.  
  1250.           can serve an application.
  1251.  
  1252.           The "locktimeout" option limits the  time  the  server  waits  to
  1253.           acquire  a  lock on behalf of the client.  The value represents a
  1254.           number of 10-second intervals.  A value of zero  means  that  the
  1255.           server  does  not wait at all, and if the lock cannot be acquired
  1256.           immediately,  the  client  operation  returns  esmFAILURE,   with
  1257.           esmLOCKBUSY  in sm_errno.  The option value can be changed at any
  1258.           time.  The value that is in effect  at  the  time  a  transaction
  1259.           makes  its  first  request to a server is the value used for lock
  1260.           requests on that server for the duration of the transaction.  See
  1261.           Appendix  A,  Section  A.3, Deadlock Detection and Avoidance, for
  1262.           more information about locks.  See also Section 4.4, Mounting and
  1263.           Dismounting  Volumes,  for  information  concerning  the protocol
  1264.           between clients and servers.
  1265.  
  1266.  
  1267.  
  1268.  
  1269.  
  1270.                                          17
  1271.  
  1272.  
  1273.  
  1274.  
  1275.  
  1276.  
  1277.  
  1278.  
  1279.  
  1280.  
  1281.           To support code that was written before the configuration  option
  1282.           facility  was added, the client library looks for the environment
  1283.           variable ESMCONFIG. If set, ESMCONFIG indicates  a  configuration
  1284.           file  to  read. The file is read using sm_ReadConfigFile( ), with
  1285.           its "programName" argument having the value  NULL.   It  is  read
  1286.           before any option is set, so all other functions that set options
  1287.           override those found in the ESMCONFIG file.
  1288.  
  1289.  
  1290.           sm_SetClientOption (optionName, optionValue, valueType)
  1291.           char            *optionName;    /* IN name of the option to set */
  1292.           void            *optionValue;   /* IN new value for the option  */
  1293.           SMDATATYPE      valueType;      /* IN type of optionValue */
  1294.  
  1295.           Sm_SetClientOption( ) sets the option named "optionName"  to  the
  1296.           value  in  "optionValue". The "valueType" arguments indicates the
  1297.           type addressed by "optionValue". The supported types are  SM_int,
  1298.           SM_Boolean, and SM_string. If "valueType" matches the type of the
  1299.           option as specified in Table 1, a simple assignment is done.   If
  1300.           "valueType"  is  SM_string and the option has a different type, a
  1301.           conversion is performed.
  1302.  
  1303.  
  1304.           sm_GetClientOption (optionName, optionValue)
  1305.           char            *optionName;    /* IN name of the option to get */
  1306.           void            *optionValue;   /* OUT value for the option  */
  1307.  
  1308.           Sm_GetClientOption( ) retrieves the value  for  "optionName"  and
  1309.           returns  it  in  "optionValue".   It is assumed that the location
  1310.           addressed by "optionValue" matches the type, found  in  Table  1,
  1311.           for  the  option.  For string-type options, the argument "option-
  1312.           Value" is treated as type "const char **pq.  That is,  it  should
  1313.           contain  the  address  of  a pointer variable that is  updated to
  1314.           point to a read-only buffer containing the option value.
  1315.  
  1316.  
  1317.           sm_ParseCommandLine (argc, argv, errorMsg)
  1318.           int             *argc;                  /* IN/OUT number of command line arguments */
  1319.           char            **argv;         /* IN/OUT command line arguments */
  1320.           char            **errorMsg;             /* OUT syntax error message */
  1321.  
  1322.           Sm_ParseCommandLine( ) searches the command line, "argv", for any
  1323.           client options.  Command-line options are prefixed by a "-".  The
  1324.           value for the option must follow the  option  name.  The  Storage
  1325.           Manager  ignores any command-line argument that is not recognized
  1326.           as a Storage Manager client option.  If a client option is found,
  1327.           the  name  and value are removed from "argv" and "argc" is decre-
  1328.           mented by 2, even if there is an error  in  the  option  such  as
  1329.           being  given  an  illegal value.  If there is an error processing
  1330.           any option, "errorMsg" is changed to point to  an  error  message
  1331.           string.
  1332.  
  1333.  
  1334.  
  1335.  
  1336.                                          18
  1337.  
  1338.  
  1339.  
  1340.  
  1341.  
  1342.  
  1343.  
  1344.  
  1345.  
  1346.  
  1347.           sm_ReadConfigFile (configFile, programName, errorMsg)
  1348.           char            *configFile;            /* IN name of the configuration file */
  1349.           char            *programName;   /* IN name of the application */
  1350.           char            **errorMsg;             /* OUT syntax error message */
  1351.  
  1352.  
  1353.           Sm_ReadConfigFile( ) reads the option configuration file "config-
  1354.           File",  and sets the options indicated.  If "configFile" is NULL,
  1355.           the  default   configuration   files   /usr/lib/exodus/sm_config,
  1356.           $HOME/.sm_config,  and  ./.sm_config   are read in that order, if
  1357.           they  exist.  The  name  of  the   default   configuration   file
  1358.           /usr/lib/exodus/sm_config  can  be  changed  with a minor Storage
  1359.           Manager source code change described in the installation  manual,
  1360.           EXODUS  Storage  Manager  Installation  Manual. The "programName"
  1361.           option gives the program name for matching with  options  in  the
  1362.           configuration  file. If "programName" is NULL and a previous call
  1363.           to sm_ReadConfigFile( ) had a non-NULL "programName", the  previ-
  1364.           ous  "programName"  is  used.  If no previous call was made and a
  1365.           "programName" is not given, configuration file lines that contain
  1366.           a  program  name  are  not  used;  only  generic entries, such as
  1367.           client.bufpages: 1000 and client*bufpages: 1000 are used.
  1368.  
  1369.           When an error occurs while reading the file, an error message  is
  1370.           stored  in  "errorMsg"  and esmFAILURE is returned, as with other
  1371.           Storage Manager functions. The  "errorMsg"  is  describes  syntax
  1372.           related errors in the configuration file.
  1373.  
  1374.           See Section 3 for information about the format  of  configuration
  1375.           files.
  1376.  
  1377.  
  1378.           sm_Initialize ( )
  1379.  
  1380.           Sm_Initialize( ) initializes the Storage Manager's   data  struc-
  1381.           tures.  No Storage Manager functions except option and configura-
  1382.           tion file functions may  be  called  before  sm_Initialize( )  is
  1383.           called.  Options  that  do  not  have defaults must be set before
  1384.           sm_Initialize( ) is called,  otherwise  esmFAILURE  is  returned,
  1385.           sm_errno is set to indicate what the problem is.
  1386.  
  1387.  
  1388.           sm_ShutDown ( )
  1389.  
  1390.           Sm_ShutDown( ) closes all the open buffer groups  and  frees  the
  1391.           memory  allocated  at  run-time  by the client library.  Once the
  1392.           client library has been shut down, it can used again  by  calling
  1393.           sm_Initialize( ).  The client library loses track the information
  1394.           in the "mount" client options, so if sm_Initialize( )  is  to  be
  1395.           used  again,  the configuration files must be reread or the mount
  1396.           options must be reset with sm_SetClientOption( ).
  1397.  
  1398.  
  1399.  
  1400.  
  1401.  
  1402.                                          19
  1403.  
  1404.  
  1405.  
  1406.  
  1407.  
  1408.  
  1409.  
  1410.  
  1411.  
  1412.  
  1413.           Figure 2 shows a simple "hello world" application for the Storage
  1414.           Manager.  It  sets  configuration options, initializes the client
  1415.           library, and shuts down the client library. A more complete  pro-
  1416.           gram  would,  begin  transactions, perform operations on objects,
  1417.           files, and indexes. More sample programs are  included  with  the
  1418.           software release.
  1419.  
  1420.  
  1421.  
  1422.  
  1423.  
  1424.               /*
  1425.                *  "Hello world" program: demonstrates initialization and shutdown.
  1426.                */
  1427.               #include <stdlib.h>
  1428.               #include "sm_client.h"
  1429.  
  1430.               void ErrorCheck (int, char *);
  1431.  
  1432.               main(int argc, char** argv) {
  1433.                   int        e;
  1434.                   char       *errorMsg;
  1435.  
  1436.                   e = sm_ReadConfigFile(NULL, argv[0], &errorMsg);
  1437.                   if (e != esmNOERROR) {
  1438.                       fprintf(stderr, "Configuration file error: %s", errorMsg);
  1439.                       ErrorCheck(e, "sm_ReadConfigFile");
  1440.                       exit(0);
  1441.                   }
  1442.                   e = sm_ParseCommandLine(&argc, argv, &errorMsg);
  1443.                   if (e != esmNOERROR) {
  1444.                       fprintf(stderr, "Command line error: %s", errorMsg);
  1445.                       ErrorCheck(e, "sm_ParseCommandLine");
  1446.                       exit(0);
  1447.                   }
  1448.  
  1449.                   e = sm_Initialize( ); ErrorCheck(e, "sm_Initialize");
  1450.                   printf("Hello world!");
  1451.                   e = sm_ShutDown( ); ErrorCheck(e, "sm_ShutDown");
  1452.               }
  1453.  
  1454.               void ErrorCheck (int e, char *func) {
  1455.                   if (e < 0) {
  1456.                       fprintf(stderr, "Storage Manager error \"%s\" in %s",
  1457.                               sm_Error(sm_errno), func);
  1458.                       exit(1);
  1459.                   }
  1460.               }
  1461.  
  1462.                            Figure 2: Example Program
  1463.  
  1464.  
  1465.  
  1466.  
  1467.  
  1468.                                          20
  1469.  
  1470.  
  1471.  
  1472.  
  1473.  
  1474.  
  1475.  
  1476.  
  1477.  
  1478.  
  1479.           4.3.  Transactions
  1480.  
  1481.           The Storage Manager supports transactions, including  concurrency
  1482.           control  and  recovery.  Transactions may involve data managed by
  1483.           several Exodus Storage Manager servers, in which case a two-phase
  1484.           commit protocol, based on Presumed Abort [Moha83], determines the
  1485.           fate of the transaction when the application commits the transac-
  1486.           tion.   The  fact  that  such  a  transaction is distributed over
  1487.           several servers is invisible to the application.   On  the  other
  1488.           hand,  the Storage Manager (server or servers) can cooperate in a
  1489.           two-phase commit procedure with other transaction processing sys-
  1490.           tems  when the external two-phase commit functions are used.  The
  1491.           external two-phase commit functions also can be  used  explicitly
  1492.           to  invoke  the  two  phases for a transaction that involves only
  1493.           Exodus Storage manager servers.  The  external  two-phase  commit
  1494.           functions  are  described  under  "Advanced  Topics",  in Section
  1495.           4.11.3, External Two-Phase Commit Functions,
  1496.  
  1497.           Object, file, index, and root entry operations must be  performed
  1498.           within  the  scope  of a transaction, or an error is returned. An
  1499.           application can run no more  than  one  transaction  at  a  time.
  1500.           Transactions cannot be nested, suspended, or resumed.
  1501.  
  1502.           In order to guarantee the semantics of  transactions,  operations
  1503.           on  objects  and  files  acquire locks.  Appendix A describes the
  1504.           kinds of locks acquired by the client library functions.
  1505.  
  1506.           4.3.1.  Transaction Identifiers
  1507.  
  1508.           Each transaction has a local  transaction  identifier,  which  is
  1509.           assigned  by the Storage Manager.  The data type TID represents a
  1510.           transaction identifier.  The application can treat a  TID  as  an
  1511.           opaque  value.   The Storage Manager maintains a global variable,
  1512.           Tid, of type TID, which value the application  can  inspect,  but
  1513.           had better not modify.
  1514.  
  1515.           The application can use the following two macros to give an  ini-
  1516.           tial  value  to  a  transaction identifier, and to recognize that
  1517.           value.
  1518.  
  1519.               INVALIDATE_TID (TID tid)
  1520.  
  1521.  
  1522.           sets the "tid" argument to an invalid transaction identifier.
  1523.  
  1524.               TID_IS_INVALID (TID tid)
  1525.  
  1526.  
  1527.           returns TRUE if "tid" is the value  given  by  INVALIDATE_TID( ),
  1528.           FALSE  if  not.   TID_IS_INVALID( )  does not tell if there is an
  1529.           active transaction with the given transaction identifier.
  1530.  
  1531.  
  1532.  
  1533.  
  1534.                                          21
  1535.  
  1536.  
  1537.  
  1538.  
  1539.  
  1540.  
  1541.  
  1542.  
  1543.  
  1544.  
  1545.           4.3.2.  Transaction States
  1546.  
  1547.           An application is always in one the following states: not running
  1548.           a transaction (INACTIVE), running a transaction (ACTIVE), running
  1549.           a transaction that has been (partially) aborted (ABORTED).
  1550.  
  1551.           An  application  is  in  the  INACTIVE  state  until   it   calls
  1552.           sm_BeginTransaction( ),      and      after     a     call     to
  1553.           sm_CommitTransaction( ) or sm_AbortTransaction( ).
  1554.  
  1555.           If the Storage Manager server or client library aborts a transac-
  1556.           tion,  which sometimes happens because of an error on the part of
  1557.           the application, the application is in the ABORTED state until  a
  1558.           call  to  sm_AbortTransaction( ).   While in the ABORTED state, a
  1559.           call to any function other than  sm_AbortTransaction( )   returns
  1560.           the error esmTRANSABORTED.
  1561.  
  1562.           4.3.3.  Transaction Operations
  1563.  
  1564.  
  1565.           sm_BeginTransaction (tid)
  1566.           TID             *tid;                   /* OUT transaction ID */
  1567.  
  1568.           Sm_BeginTransaction( ) is called at the beginning of  a  transac-
  1569.           tion.  The argument "tid" corresponds to a transaction identifier
  1570.           and is assigned by the Storage Manager.
  1571.  
  1572.           Sm_BeginTransaction( ) does not contact any servers or initiate a
  1573.           transaction with any server, since the operation has no arguments
  1574.           to indicate which servers are of  interest.   It  only  begins  a
  1575.           transaction "locally".  Once a transaction has begun locally, the
  1576.           client library initiates transactions on servers when data refer-
  1577.           ences so require.
  1578.  
  1579.  
  1580.           sm_CommitTransaction (tid)
  1581.           TID             tid;                    /* IN transaction ID */
  1582.  
  1583.           Sm_CommitTransaction( ) is called to  commit  the  effects  of  a
  1584.           transaction.  If  the  commit  succeeds, all changes made to data
  1585.           since the beginning of the transaction are guaranteed to be  per-
  1586.           sistent,  even in the event of system failure. See Section 4.9.1,
  1587.           Consistency Guarantees for Files, for more information about this
  1588.           guarantee.  If  the  commit  fails, an error is returned, and the
  1589.           transaction is aborted. When a transaction is committed, all user
  1590.           descriptors  (see  sm_ReadObject( ) ) are released. Buffer groups
  1591.           attached to the  transaction  (see  sm_OpenBufferGroup( )  )  are
  1592.           closed.
  1593.  
  1594.  
  1595.           sm_AbortTransaction (tid)
  1596.           TID             tid;                    /* IN transaction ID */
  1597.  
  1598.  
  1599.  
  1600.                                          22
  1601.  
  1602.  
  1603.  
  1604.  
  1605.  
  1606.  
  1607.  
  1608.  
  1609.  
  1610.  
  1611.           Sm_AbortTransaction( )        aborts        a        transaction.
  1612.           Sm_AbortTransaction( )  releases  all  the  user descriptors that
  1613.           were created during  the  transaction  (see  sm_ReadObject( )  ).
  1614.           Buffer     groups    attached    to    the    transaction    (see
  1615.           sm_OpenBufferGroup( ) ) are closed.
  1616.  
  1617.           The persistent data appear as if  the  transaction  never  began.
  1618.           The execution state of the application program is not affected by
  1619.           calling sm_AbortTransaction( ).  The result is that the transient
  1620.           data in the program's address space do not match the state of the
  1621.           persistent data.  The problem can be alleviated to some degree by
  1622.           judicious  use  of  setjmp(2), longjmp(2), and lexical scoping in
  1623.           the application program.  The following macros, which are defined
  1624.           in sm_client.h, do that:
  1625.  
  1626.  
  1627.           SM_BEGIN_TRANSACTION (tid, abortCode)
  1628.           TID             *tid;                   /* transaction ID */
  1629.           int             abortCode;              /* location to store abort code */
  1630.  
  1631.           SM_BEGIN_TRANSACTION begins a transaction block (i.e. it opens  a
  1632.           new  lexical scope in C or C++).  The transaction ID is placed in
  1633.           "tid".  The argument "abortCode" must be a variable.  This  vari-
  1634.           able  can  be checked at the end of the transaction to determined
  1635.           if it was aborted.
  1636.  
  1637.  
  1638.           SM_COMMIT_TRANSACTION (tid)
  1639.           TID             tid;                    /* transaction ID */
  1640.  
  1641.           SM_COMMIT_TRANSACTION ends a transaction block. When this  state-
  1642.           ment is executed, the transaction is committed, assuming no error
  1643.           occurs during commit. Immediately after the SM_COMMIT_TRANSACTION
  1644.           statement,    the    "abortCode"    variable    given    in   the
  1645.           SM_BEGIN_TRANSACTION statement should be checked to  see  if  any
  1646.           error  occurred.  If  no  error  occurred,  "abortCode" is set to
  1647.           esmNOERROR. Otherwise, "abortCode" is set to the value  given  in
  1648.           SM_ABORT_TRANSACTION.
  1649.  
  1650.  
  1651.           SM_ABORT_TRANSACTION (abortCode)
  1652.           int             abortCode;              /* error to return on abort */
  1653.  
  1654.           SM_ABORT_TRANSACTION  aborts   the   active   transaction   (i.e.
  1655.           sm_AbortTransaction( )  is  called)  and resumes execution at the
  1656.           line immediately following  the  SM_COMMIT_TRANSACTION  statement
  1657.           for the transaction. The SM_ABORT_TRANSACTION macro does not need
  1658.           to be called within the lexical scope of the  transaction  block.
  1659.           It  can  be called in any function operating in the dynamic scope
  1660.           of  the  transaction.   The   "abortCode"   argument   sets   the
  1661.           "abortCode" variable given in SM_BEGIN_TRANSACTION.
  1662.  
  1663.  
  1664.  
  1665.  
  1666.                                          23
  1667.  
  1668.  
  1669.  
  1670.  
  1671.  
  1672.  
  1673.  
  1674.  
  1675.  
  1676.  
  1677.           When a SM_ABORT_TRANSACTION is called, the program's  control  is
  1678.           transferred  to the program point after the SM_COMMIT_TRANSACTION
  1679.           statement. The stack pointer is restored  to  the  level  of  the
  1680.           transaction  block,  so functions on the program's stack after it
  1681.           are not completed. For C++, this means that destructors  are  not
  1682.           called for any local variables in those functions.
  1683.  
  1684.           Examples of using both the transaction macros and  functions  can
  1685.           be  found  in  the producer-consumer example given in the Storage
  1686.           Manager software release.
  1687.  
  1688.           4.4.  Mounting and Dismounting Volumes
  1689.  
  1690.           An application program  does  not  need  to  mount  and  dismount
  1691.           volumes  explicitly.  In most cases, the client library automati-
  1692.           cally mounts a volume when the application makes its first refer-
  1693.           ence  to  that  volume.   An application that does not explicitly
  1694.           mount a volume may, when it performs its first  operation  on  an
  1695.           object,  find  that  the  server  for that object is not running.
  1696.           Writing programs to handle such common errors can  be  difficult,
  1697.           so  it  may be more convenient to mount volumes before proceeding
  1698.           with operations on data.  Sm_MountVolume( ) serves that  purpose.
  1699.           If  that  server  has  not  yet been contacted, sm_MountVolume( )
  1700.           establishes a connection to the server and mounts the volume.  It
  1701.           does  not  begin  a transaction.  (See Section 4.3.3, Transaction
  1702.           Operations to understand how transactions are begun.)
  1703.  
  1704.           When an application exits or calls sm_ShutDown( ), connections to
  1705.           servers are severed, and the servers dismount the volumes used by
  1706.           the application.  A server severs its connections  and  dismounts
  1707.           the volumes if an application is inactive for a significant time.
  1708.           An application is inactive if it has no transaction running.
  1709.  
  1710.           An application  can  dismount  volumes  explicitly,  causing  the
  1711.           volumes to be dismounted at the server.  An application that con-
  1712.           tinues to run after it is  finished  using  the  Storage  Manager
  1713.           would  do  well to use sm_ShutDown( ).  If it is inappropriate to
  1714.           use sm_ShutDown( ), but such an application is  finished  with  a
  1715.           set of volumes, it would do best to dismount the volumes, partic-
  1716.           ularly if the volumes are likely to be reformatted.
  1717.  
  1718.  
  1719.           sm_MountVolume ( volid )
  1720.           VOLID   volid;                  /* IN volume to mount */
  1721.  
  1722.  
  1723.           Sm_MountVolume( ) causes the volume identified by "volid"  to  be
  1724.           mounted.   A  side  effect  of  the  operation is that the client
  1725.           library has established a connection with the server that manages
  1726.           this volume.
  1727.  
  1728.  
  1729.  
  1730.  
  1731.  
  1732.                                          24
  1733.  
  1734.  
  1735.  
  1736.  
  1737.  
  1738.  
  1739.  
  1740.  
  1741.  
  1742.  
  1743.           If  the  volume  cannot  be  mounted,  sm_MountVolume( )  returns
  1744.           esmFAILURE  and  a  value  in sm_errno that describes the reason:
  1745.           esmNOSUCHVOLUME (the client library cannot  identify  the  server
  1746.           for  this  volume  because  there  is  no "mount" option for this
  1747.           volid), esmTRANSABORTED (the transaction was aborted  during  the
  1748.           previous operation, and the next thing the application must do is
  1749.           abort the transaction), esmSERVERDIED (connection with server was
  1750.           severed  during  the  mount operation), or any Unix error message
  1751.           from <errno.h> (such as ENETDOWN and ECONNREFUSED),  which  indi-
  1752.           cate that the server is not running or is unreachable through the
  1753.           network.
  1754.  
  1755.  
  1756.           sm_DismountVolume ( volid )
  1757.           VOLID   volid;                  /* IN volume to dismount */
  1758.  
  1759.  
  1760.           The "volid" argument identifies the volume to be dismounted.   If
  1761.           the  volume is not mounted, the operation returns esmFAILURE, and
  1762.           the client library returns esmBADVOLID in sm_errno.
  1763.  
  1764.           4.5.  Root Entries
  1765.  
  1766.           The root entry facility is designed for  applications  to  get  a
  1767.           handle to data on a volume.  [1] A common use of a root entry  is
  1768.           to  associate  a  string  name  with  an object identifier for an
  1769.           object containing information about the contents of  the  volume.
  1770.           For example, in a database system, this might be the object iden-
  1771.           tifier for the catalog.
  1772.  
  1773.           A root entry is a string and data pair stored in a special  loca-
  1774.           tion  on  a  volume, called the root area. The string, called the
  1775.           name, is used to identify the entry.  The  name  string  must  be
  1776.           null-terminated.  The  maximum lengths of the name (including the
  1777.           terminating null) and data are defined by  MAX_ROOTNAME_SIZE  and
  1778.           MAX_ROOTDATA_SIZE  respectively.  An  error  is  returned  if the
  1779.           available number of root entries is exceeded. Names and data  are
  1780.           limited  to  32 bytes each, and approximately 90 root entries can
  1781.           reside in a volume's root area.
  1782.  
  1783.  
  1784.           sm_SetRootEntry (volid, name, data, dataLength)
  1785.           VOLID   volid;                  /* IN volume identifier */
  1786.           char            *name;          /* IN name to store data entry under */
  1787.           void            *data;                  /* IN data entry to be stored */
  1788.           int             dataLength;             /* IN length of the data */
  1789.  
  1790.  
  1791.           ____________________
  1792.              [1] Root entries cannot be created on temporary volumes.
  1793.  
  1794.  
  1795.  
  1796.  
  1797.  
  1798.                                          25
  1799.  
  1800.  
  1801.  
  1802.  
  1803.  
  1804.  
  1805.  
  1806.  
  1807.  
  1808.  
  1809.           Sm_SetRootEntry( ) is creates or updates  an  entry.  The  "name"
  1810.           argument  is the name of the entry and the "data" argument is the
  1811.           data to be stored. The number of bytes in the data  is  given  in
  1812.           "dataLength".  For example, to store the contents of the variable
  1813.           "rootOid" under the name "root-obj",  use  sm_SetRootEntry(volid,
  1814.           "root-obj", (char*) &rootOid, sizeof(rootOid)).
  1815.  
  1816.           Sm_SetRootEntry( ) obtains an exclusive lock on the root area  of
  1817.           the  volume,  so updates to root entries should be performed in a
  1818.           short transaction.
  1819.  
  1820.  
  1821.           sm_GetRootEntry (volid, name, data, dataLength)
  1822.           VOLID   volid;                  /* IN volume identifier */
  1823.           char            *name;          /* IN name of the entry */
  1824.           void            *data;                  /* OUT data stored under name */
  1825.           int             *dataLength;            /* IN/OUT length of the data */
  1826.  
  1827.           Sm_GetRootEntry( ) retrieves the root entry  named  "name".   The
  1828.           data  is  placed in "data" and the length of the data is returned
  1829.           in "dataLength".  If "dataLength" is  initialized  with  a  value
  1830.           greater than or equal to zero, the maximum number of bytes copied
  1831.           to "data" is "dataLength".  If "dataLength" is initialized with a
  1832.           value  less than zero, the entire length of the data is copied to
  1833.           "data".
  1834.  
  1835.           Sm_GetRootEntry( ) obtains a share lock on the root area  of  the
  1836.           volume.  This  share lock blocks other transactions from updating
  1837.           or removing root entries until the transaction  is  committed  or
  1838.           aborted.  If  no  root  entry  exists  for  "name", esmFAILURE is
  1839.           returned and sm_errno is set to esmBADROOTNAME.
  1840.  
  1841.  
  1842.           sm_RemoveRootEntry (volid, name)
  1843.           VOLID   volid;                  /* IN volume identifier */
  1844.           char            *name;          /* IN name of entry */
  1845.  
  1846.  
  1847.           Sm_RemoveRootEntry( ) removes the root entry stored under "name".
  1848.           Sm_RemoveRootEntry( )  obtains an exclusive lock on the root area
  1849.           of the volume, so removal of root entries should be performed  in
  1850.           a short transaction.
  1851.  
  1852.           4.6.  Buffer Operations
  1853.  
  1854.           The Storage Manager buffer manager implements the  concept  of  a
  1855.           buffer  group,  as  proposed in the DBMIN buffer management algo-
  1856.           rithm [Chou85]. The essence of the DBMIN algorithm is  that  com-
  1857.           peting  uses  of  the  buffer  pool  may  be  allocated their own
  1858.           buffers, to minimize competition for the buffers and to eliminate
  1859.           thrashing in the buffer pool.
  1860.  
  1861.  
  1862.  
  1863.  
  1864.                                          26
  1865.  
  1866.  
  1867.  
  1868.  
  1869.  
  1870.  
  1871.  
  1872.  
  1873.  
  1874.  
  1875.           All uses of the buffer pool are made through a buffer  group.   A
  1876.           buffer  group is a container of page buffers, with a limit on the
  1877.           number of fixed pages it can contain.  Fixed pages are guaranteed
  1878.           to  remain in the buffer pool until they are unfixed. Their loca-
  1879.           tions (virtual addresses) may change, but the pages remain in the
  1880.           virtual  address space of the buffer pool.  Each buffer group has
  1881.           a replacement policy, which controls the replacement  of  unfixed
  1882.           pages within the buffer group.
  1883.  
  1884.           Buffer groups can be opened and closed at any  time,  whether  or
  1885.           not  a  transaction is running.  If a buffer group is opened in a
  1886.           transaction, it may be "attached" to the transaction, which means
  1887.           that  the  buffer  group is closed by the client library when the
  1888.           transaction ends.  An attached buffer group can be closed  expli-
  1889.           citly by the application before the transaction ends.
  1890.  
  1891.           The following two macros can be used with buffer groups  to  give
  1892.           an  initial  value  to a buffer group index and to recognize that
  1893.           value.
  1894.  
  1895.               INVALIDATE_BUFGROUP (int bufgroup)
  1896.  
  1897.  
  1898.           sets the "bufgroup" argument to an invalid buffer group index.
  1899.  
  1900.               BUFGROUP_IS_INVALID (int bufgroup)
  1901.  
  1902.  
  1903.           returns   TRUE   if   "bufgroup"   is   the   value   given    by
  1904.           INVALIDATE_BUFGROUP( ),      FALSE      if     it     is     not.
  1905.           BUFGROUP_IS_INVALID( ) does not tell if  there  exists  a  buffer
  1906.           group with the given index.
  1907.  
  1908.  
  1909.           sm_OpenBufferGroup (groupSize, policy, groupIndex, flags)
  1910.           int             groupSize;              /* IN the maximum group size in pages */
  1911.           int             policy;                 /* IN the group's replacement policy */
  1912.           int             *groupIndex;            /* OUT the group's index */
  1913.           FLAGS    flags;                 /* IN buffer group attributes */
  1914.  
  1915.  
  1916.           Sm_OpenBufferGroup( ) opens a new buffer group.  The  "groupSize"
  1917.           argument  specifies  the size of the buffer group in MIN_PAGESIZE
  1918.           pages. The sum of the sizes of  all  open  buffer  groups  cannot
  1919.           exceed  the size of the buffer pool.  (See Section 4.11.3, Tuning
  1920.           the Application.)  The choice for "policy" is least-recently-used
  1921.           (BF_LRU)  or  most-recently-used (BF_MRU).  BF_LRU and BF_MRU are
  1922.           defined in sm_client.h.  The argument "groupIndex" is  filled  by
  1923.           the  Storage Manager and must be used in subsequent references to
  1924.           the buffer group.  (All operations on files and objects require a
  1925.           buffer group index.)
  1926.  
  1927.  
  1928.  
  1929.  
  1930.                                          27
  1931.  
  1932.  
  1933.  
  1934.  
  1935.  
  1936.  
  1937.  
  1938.  
  1939.  
  1940.  
  1941.           The "flags" indicates whether the buffer group is to  be  associ-
  1942.           ated  with  a  transaction.   NOFLAGS  indicates  that it is not.
  1943.           TRANS_GROUP indicates that the buffer group  is  associated  with
  1944.           the  current  transaction.  The  group  is  closed  by the client
  1945.           library when the active transaction ends. If TRANS_GROUP is used,
  1946.           a  transaction  must be running at the time sm_OpenBufferGroup( )
  1947.           is called.
  1948.  
  1949.           The effect of sm_OpenBufferGroup( )  is  to  reserve  "groupSize"
  1950.           pages  in  the client's buffer pool. No buffer group is opened on
  1951.           the server.
  1952.  
  1953.  
  1954.           sm_BufferGroupInfo (groupIndex, maxPages, fixedPages, unfixedPages)
  1955.           int             groupIndex;             /* IN the group to inspect */
  1956.           int             *maxPages;              /* OUT max fixed pages allowed      */
  1957.           int             *fixedPages;            /* OUT current # of pages fixed     */
  1958.           int             *unfixedPages;  /* OUT current # of pages unfixed   */
  1959.  
  1960.  
  1961.           Sm_BufferGroupInfo( ) returns information about the  open  buffer
  1962.           group  identified  by  "groupIndex".   The  function  returns the
  1963.           buffer group's size limit  in  pages  in  "maxPages".   In  "fix-
  1964.           edPages",  it  returns the number of pages currently fixed in the
  1965.           buffer group.  See the next section for  more  information  about
  1966.           these  functions.   The  argument  "unfixedPages"  refers  to all
  1967.           buffer pages that belong to the buffer group, but are not  fixed,
  1968.           that  is these pages may be removed from the buffer pool if space
  1969.           is needed for fixed pages.
  1970.  
  1971.  
  1972.           sm_CloseBufferGroup (groupIndex)
  1973.           int             groupIndex;             /* IN the group being closed */
  1974.  
  1975.           Sm_CloseBufferGroup( ) closes the open buffer group identified by
  1976.           "groupIndex".
  1977.  
  1978.  
  1979.           4.7.  Operations on Objects
  1980.  
  1981.           An object in the Storage Manager is a container of bytes. It  can
  1982.           be  empty.   It can have as many as 2[31] bytes, if the volume on
  1983.           which it resides is large enough.  An object must fit on a single
  1984.           volume (storage device or partition).  When an object is created,
  1985.           the Storage Manager gives the object a unique object  identifier.
  1986.           An object identifier is described by a structure of the type OID,
  1987.           defined as follows:.
  1988.  
  1989.  
  1990.  
  1991.  
  1992.  
  1993.  
  1994.  
  1995.  
  1996.                                          28
  1997.  
  1998.  
  1999.  
  2000.  
  2001.  
  2002.  
  2003.  
  2004.  
  2005.  
  2006.  
  2007.               typedef struct {
  2008.                      SHORTPID pid;                    /* 32-bit page address of the object's header */
  2009.                      SLOTINDEX        slot;           /* 16-bit slot number of the object on the page */
  2010.                      VOLID            volid;          /* 16-bit identifier of the volume */
  2011.                      UNIQUE           unique; /* 32-bit number generated at creation time */
  2012.               } OID;
  2013.  
  2014.  
  2015.           The first three fields of an OID are the physical address of  the
  2016.           object;  they  identify a volume, a page within the volume, and a
  2017.           slot on the page.  An  object's  identifier  never  changes.  The
  2018.           client  library  sometimes  moves objects, such as when an object
  2019.           grows beyond the size of a page, at  which  time  the  object  is
  2020.           marked as forwarded, but its OID remains unchanged.
  2021.  
  2022.           The "unique" field of an OID is special 32-bit value that is gen-
  2023.           erated when the object is created and used to detect dangling and
  2024.           corrupted OIDs.  The generation of unique numbers is discussed in
  2025.           Appendix B.
  2026.  
  2027.           Every time an object is accessed by its OID, the Storage  Manager
  2028.           validates  the OID.  The application can use the following macros
  2029.           to give an illegitimate initial value to an OID, and to recognize
  2030.           that value:
  2031.  
  2032.               INVALIDATE_OID (OID oid)
  2033.  
  2034.           sets the "oid" argument to an invalid object identifier.
  2035.  
  2036.               OID_IS_INVALID (OID oid)
  2037.  
  2038.           returns TRUE if "oid" is the value  given  by  INVALIDATE_OID( ),
  2039.           FALSE if it is not.
  2040.  
  2041.           Each object has an object header, which describes the object, and
  2042.           which can be retrieved without retrieving the object's data.  The
  2043.           structure of an object header is shown below:
  2044.  
  2045.               typedef struct {
  2046.                      TWO      properties;     /* a bit vector */
  2047.                      TWO      tag;            /* supplied by the application */
  2048.                      int              size;           /* size of the object in bytes */
  2049.               } OBJHDR;
  2050.  
  2051.  
  2052.           The "tag" is a two-byte field that the Storage Manager  does  not
  2053.           interpret.   It is for use by the application.  No restriction is
  2054.           put on the contents of "tag" fields.  As its  name  implies,  the
  2055.           "size"  field  is  the size of the object in bytes.  The "proper-
  2056.           ties" field is a read-only bit-vector that indicates the presence
  2057.           or absence of the following properties of objects:
  2058.  
  2059.  
  2060.  
  2061.  
  2062.                                          29
  2063.  
  2064.  
  2065.  
  2066.  
  2067.  
  2068.  
  2069.  
  2070.  
  2071.  
  2072.  
  2073.  
  2074.                 P_LARGEOBJ       set if the object is a large object.
  2075.  
  2076.                 P_MOVED          set if this object has been  forwarded
  2077.                                  to another page.
  2078.  
  2079.                 P_FROZEN         set if the object is a frozen version.
  2080.  
  2081.                 P_VERSIONED      set if the object is a frozen  version
  2082.                                  or a descendent of a frozen version.
  2083.  
  2084.  
  2085.           Each object resides in a file on a volume.   When  an  object  is
  2086.           created,  the  application tells the client library in which file
  2087.           to place the object.  Files and their uses are discussed  in  the
  2088.           next  section;  details  of their use are not pertinent to under-
  2089.           standing the operations on objects.
  2090.  
  2091.           Before an operation can be performed on an existing  object,  the
  2092.           object,  or  at  least  the affected parts of the object, must be
  2093.           brought into the application's address  space.   This  is  called
  2094.           pinning  the  object  or its parts.  When the object is no longer
  2095.           needed, it must be unpinned, to make room for other objects to be
  2096.           pinned[2].  When the client library pins and object in  order  to
  2097.           perform  an  operation on behalf of the application (for example,
  2098.           appending bytes to an object), the client library pins the neces-
  2099.           sary  parts  of the object and unpins them before it returns con-
  2100.           trol to the application.  When the application pins  part  of  an
  2101.           object  for  its  own purposes (such as writing over bytes in the
  2102.           object), the pinned part is placed in the client's  buffer  pool,
  2103.           and the client library creates a "handle" for the the object. The
  2104.           handle is called a user descriptor.  The application can refer to
  2105.           an  object  only  through user descriptors.  The application must
  2106.           unpin the object by releasing the user descriptor when it is done
  2107.           using the object.
  2108.  
  2109.           A user descriptor is called valid if and only if the  byte  range
  2110.           it  addresses  is  pinned.   An  application can pin an object or
  2111.           overlapping parts of an object any number of  times,  having  any
  2112.           number  of valid user descriptors for the same data in an object.
  2113.           (This is not wise for performance reasons, but it can be done.)
  2114.  
  2115.           The client library functions that pin ranges of bytes return user
  2116.           descriptors to describe the bytes pinned.  Functions that require
  2117.           that the range of bytes they affect be pinned take user  descrip-
  2118.           tors  as  input  arguments.  The client library functions that do
  2119.           not take user descriptor arguments do not ultimately  change  the
  2120.           ____________________
  2121.              [2] Objects are pinned; pages are fixed.  The gist of the  two
  2122.           verbs is the same.
  2123.  
  2124.  
  2125.  
  2126.  
  2127.  
  2128.                                          30
  2129.  
  2130.  
  2131.  
  2132.  
  2133.  
  2134.  
  2135.  
  2136.  
  2137.  
  2138.  
  2139.           quantity of bytes pinned or the number  of  pages  fixed  in  the
  2140.           buffer  pool.  Such  functions   may  change  the ranges of bytes
  2141.           addressed or the bytes themselves, but they  do  not  change  the
  2142.           quantity   of   bytes  addressed.   (For  example,  the  function
  2143.           sm_InsertInObject( )  may  affect  valid  user  descriptors  even
  2144.           though it does not take and user descriptors as arguments.)
  2145.  
  2146.           User descriptors have the following form:
  2147.  
  2148.               typedef struct {
  2149.                      char             *basePtr;       /* ptr to start of data */
  2150.                      int                      byteCount       /* number of bytes accessible */
  2151.                      int                      objectSize;     /* total size of object */
  2152.                      TWO              userFlags;      /* properties field from object header */
  2153.                      TWO              type;           /* for use only  by E */
  2154.                      TWO              flags;          /* for use only  by E */
  2155.                      TWO              tag;            /* tag field from the object header */
  2156.                      OID              oid;            /* oid of object being referenced */
  2157.               } USERDESC;
  2158.  
  2159.  
  2160.           The "basePtr" field of a user descriptor points to the  start  of
  2161.           the object's data in the buffer pool, while the "byteCount" field
  2162.           indicates the number of bytes accessible to the application  pro-
  2163.           gram through this user descriptor.  The value "objectSize" is the
  2164.           length of the entire object. The "userFlags" field holds  a  copy
  2165.           of the  properties field from the object's header. The "type" and
  2166.           "flags" fields are used by the E  language's  persistent  virtual
  2167.           machine.  Finally,  the  "tag" field contains a copy of the "tag"
  2168.           field in the object's header.
  2169.  
  2170.           An object's data  is  referenced  indirectly  via  the  "basePtr"
  2171.           field.  References by the application must always be indirect via
  2172.           "basePtr".  The indirection is necessary because there are  times
  2173.           when  the Storage Manager moves an object in the buffer pool, and
  2174.           the "basePtr" of each user descriptor that references the  object
  2175.           is updated to account for the move.
  2176.  
  2177.           The remainder of this section describes the Storage Manager func-
  2178.           tions  for  operating on objects. It is divided into sub-sections
  2179.           that describe creating and destroying objects, pinning and unpin-
  2180.           ning  parts  of  objects,  modifying  objects,  and  using object
  2181.           headers.
  2182.  
  2183.           4.7.1.  Creating and Destroying Objects
  2184.  
  2185.  
  2186.  
  2187.  
  2188.  
  2189.  
  2190.  
  2191.  
  2192.  
  2193.  
  2194.                                          31
  2195.  
  2196.  
  2197.  
  2198.  
  2199.  
  2200.  
  2201.  
  2202.  
  2203.  
  2204.  
  2205.           sm_CreateObject (groupIndex, fid, nearHint, nearObj, objHdr, length, data, oid)
  2206.           int              groupIndex;            /* IN buffer group to use */
  2207.           FID             *fid;                   /* IN file in which object is to be placed */
  2208.           int              nearHint;              /* IN flag indicating where to create the new object */
  2209.           OID             *nearObj;               /* IN create the new object near this object */
  2210.           OBJHDR          *objHdr;                /* IN the object's header */
  2211.           int              length;                /* IN amount of data */
  2212.           void            *data;                  /* IN the initial data for the object */
  2213.           OID             *oid;                   /* OUT the new object's OID */
  2214.  
  2215.  
  2216.           Sm_CreateObject( ) creates an object in the  file  identified  by
  2217.           "fid".  If "objHdr" is not NULL, the "tag" field in the header of
  2218.           the new object is initialized with  the  contents  of  the  "tag"
  2219.           field in the header structure addressed by "objHdr".  When "data"
  2220.           is not NULL, the object is initialized with the data addressed by
  2221.           the  argument  "data";  in this case, "length" specifies how much
  2222.           data to copy.  When "data" is NULL, an object of size "length" is
  2223.           created and filled with zeroes.
  2224.  
  2225.           The argument "nearHint" specifies where the new object should  be
  2226.           created.  The  following values, defined in sm_client.h, are near
  2227.           hints: NEAR_OBJ, NEAR_FIRST, and NEAR_LAST. If "nearHint" is  set
  2228.           to NEAR_OBJ, the new object is created near the object designated
  2229.           by "nearObj". If "nearHint" is set to  NEAR_FIRST  or  NEAR_LAST,
  2230.           "nearObj" is ignored and the new object is created near the first
  2231.           or last object in the file, respectively.
  2232.  
  2233.           If sm_CreateObject( ) is successful, the OID structure pointed to
  2234.           by   "oid"   is   filled   with   the  OID  of  the  new  object.
  2235.           Sm_CreateObject( ) does not leave the new object pinned.
  2236.  
  2237.           sm_DestroyObject (groupIndex, oid)
  2238.           int              groupIndex;            /* IN buffer group in use */
  2239.           OID             *oid;                   /* IN the object to destroy */
  2240.  
  2241.  
  2242.           Sm_DestroyObject( ) destroys an object.  If any user  descriptors
  2243.           are  valid  for the object when the object is destroyed, they are
  2244.           made invalid, and they must be released with sm_ReleaseObject( ),
  2245.           described below.
  2246.  
  2247.           4.7.2.  Pinning and Unpinning Objects
  2248.  
  2249.  
  2250.           The following two functions change the number of pages  fixed  in
  2251.           the  client buffer pool.  All the other functions that operate on
  2252.           objects fix pages temporarily and unfix the pages before  return-
  2253.           ing.
  2254.  
  2255.  
  2256.  
  2257.  
  2258.  
  2259.  
  2260.                                          32
  2261.  
  2262.  
  2263.  
  2264.  
  2265.  
  2266.  
  2267.  
  2268.  
  2269.  
  2270.  
  2271.           sm_ReadObject (groupIndex, oid, start, length, userDesc)
  2272.           int              groupIndex;            /* IN buffer group in use */
  2273.           OID              *oid;                  /* IN object to read */
  2274.           int             start;                  /* IN starting offset of read */
  2275.           int             length;         /* IN amount of data to read */
  2276.           USERDESC        **userDesc;             /* OUT descriptor to access the data */
  2277.  
  2278.  
  2279.           Sm_ReadObject( ) reads part or all of the  object  identified  by
  2280.           "oid"  into  the  buffer  group  identified  by "groupIndex".  If
  2281.           "length" is READ_ALL, the entire object is  read  (assuming  that
  2282.           the  size  of the entire object is not greater than the amount of
  2283.           unpinned space in the buffer group).  Otherwise, the bytes to  be
  2284.           read are specified by "start" and "length".
  2285.  
  2286.           Sm_ReadObject( ) pins the specified range of bytes in the  buffer
  2287.           pool  and  returns a user descriptor to the caller.  Bytes pinned
  2288.           in the buffer pool by sm_ReadObject( ) remain pinned  until  they
  2289.           are explicitly released by sm_ReleaseObject( ).
  2290.  
  2291.           While sm_ReadObject( ) can be used to get information  about  the
  2292.           object  (from  the  object header) by giving it a length of zero,
  2293.           sm_ReadObjectHeader( ) is the preferred  way  to  meet  the  same
  2294.           objective.  Sm_ReadObject( )  performs  work  that is unnecessary
  2295.           when only the object header is of interest, and it  always  fixes
  2296.           at least one page in the buffer pool, even if the given length is
  2297.           zero.
  2298.  
  2299.           The user descriptor consumes resources that must  be  freed  with
  2300.           sm_ReleaseObject( ),  even  if  the object is not pinned (zero is
  2301.           given for "length").
  2302.  
  2303.  
  2304.           sm_ReleaseObject (userDesc)
  2305.           USERDESC        *userDesc;              /* IN descriptor returned by ReadObject */
  2306.  
  2307.  
  2308.           Sm_ReleaseObject( ) unpins a range of bytes of an object that was
  2309.           pinned  by  sm_ReadObject( ),  and frees the resources associated
  2310.           with the user descriptor.  If the user descriptor is  not  valid,
  2311.           sm_ReleaseObject( )  sets  sm_errno to esmBADUSERDESC and returns
  2312.           esmFAILURE.
  2313.  
  2314.           4.7.3.  Modifying Objects
  2315.  
  2316.           Four     functions     modify     objects:     sm_WriteObject( ),
  2317.           sm_InsertInObject( ),          sm_AppendToObject( ),          and
  2318.           sm_DeleteFromObject( ).   Sm_WriteObject( )  cannot  be  used  to
  2319.           change  the  size  of  an  object,  only to overwrite parts of an
  2320.           object.  The other three functions can  change  the  size  of  an
  2321.           object.   These  functions  provide  substantial flexibility, and
  2322.           their efficiency varies.  Changing the size  of  a  small  object
  2323.  
  2324.  
  2325.  
  2326.                                          33
  2327.  
  2328.  
  2329.  
  2330.  
  2331.  
  2332.  
  2333.  
  2334.  
  2335.  
  2336.  
  2337.           (one  that  fits on a disk page) is relatively inexpensive. It is
  2338.           less expensive than reading and writing  the  object.  For  large
  2339.           objects,  performing  many small-size changes can be expensive in
  2340.           CPU time and buffer space utilization.   If  a  large  object  is
  2341.           pinned  several  times  simultaneously,  through  different  user
  2342.           descriptors, updates to the object  are  very  expensive.   If  a
  2343.           large  number  of  small-size  changes  is required, we recommend
  2344.           accumulating the changes and performing them in larger chunks.
  2345.  
  2346.  
  2347.           sm_WriteObject (groupIndex, start, length, data, userDesc, release)
  2348.           int              groupIndex;            /* IN buffer group in use */
  2349.           int             start;                  /* IN starting offset of write */
  2350.           int             length;         /* IN amount of data to be written */
  2351.           void            *data;                  /* IN pointer to the data */
  2352.           USERDESC        *userDesc;              /* IN descriptor returned by ReadObject */
  2353.           BOOL             release;               /* IN whether to release the object */
  2354.  
  2355.  
  2356.           Sm_WriteObject( ) overwrites the region of bytes from  (userDesc-
  2357.           >baseptr   + start)  to (userDesc->baseptr +  start + length - 1)
  2358.           with the data addressed by the "data" argument.  The  given  byte
  2359.           range must have been pinned (which means that the user descriptor
  2360.           must be valid).  If "release" is TRUE, the range of  bytes  given
  2361.           by  "userDesc"  is  unpinned  when sm_WriteObject( ) returns.  If
  2362.           "data" is NULL, the region is filled with zeroes.  All updates to
  2363.           objects  must  be  performed  using sm_WriteObject( ) so that the
  2364.           updates can be logged,  and  the  transaction  semantics  can  be
  2365.           guaranteed.
  2366.  
  2367.  
  2368.           sm_InsertInObject (groupIndex, oid, start, length, data)
  2369.           int              groupIndex;            /* IN buffer group in use */
  2370.           OID             *oid;                   /* IN object we're inserting into */
  2371.           int             start;                  /* IN starting offset of insert */
  2372.           int             length;         /* IN amount of data being inserted */
  2373.           void            *data;                  /* IN data to insert */
  2374.  
  2375.  
  2376.           Sm_InsertInObject( ) inserts  "length"  bytes  of  data  into  an
  2377.           object,  beginning at the offset "start".  If "data" is NULL, the
  2378.           inserted region is filled with zeroes.  If there  are  any  valid
  2379.           user  descriptors  (those  for  which sm_ReleaseObject( ) has not
  2380.           been called) for the object  at  the  time  the  insertion  takes
  2381.           place, they are reestablished if necessary.  After the insertion,
  2382.           the base pointers of the valid user descriptors point to the byte
  2383.           within  the  object  indicated  by  the  "start"  argument to the
  2384.           sm_ReadObject( ) operation that created the user descriptor.  For
  2385.           example,  an  object's  first  five  bytes, "ABCDE" are pinned by
  2386.           sm_ReadObject( ), which was called with a "start" offset of  zero
  2387.           and a "length" of five.  Sm_ReadObject( ) returns a user descrip-
  2388.           tor, U, which addresses  "ABCDE".   Sm_InsertInObject( )  inserts
  2389.  
  2390.  
  2391.  
  2392.                                          34
  2393.  
  2394.  
  2395.  
  2396.  
  2397.  
  2398.  
  2399.  
  2400.  
  2401.  
  2402.  
  2403.           "ZZ" at "start" offset zero.  The user descriptor U now addresses
  2404.           "ZZABC", which are pinned, while the bytes  "DE"  are  no  longer
  2405.           pinned.
  2406.  
  2407.  
  2408.           sm_AppendToObject (groupIndex, oid, length, data)
  2409.           int              groupIndex;            /* IN buffer group in use */
  2410.           OID             *oid;                   /* IN object we are appending data to */
  2411.           int             length;         /* IN amount of data being appended */
  2412.           void            *data;                  /* IN data to append */
  2413.  
  2414.  
  2415.           Sm_AppendToObject( ) appends "length" bytes of data to the end of
  2416.           an object.  Outstanding user descriptors are handled the same way
  2417.           as sm_InsertInObject( ).  If "data" is NULL, the appended  region
  2418.           is filled with zeroes.
  2419.  
  2420.  
  2421.           sm_DeleteFromObject (groupIndex, oid, start, length)
  2422.           int              groupIndex;            /* IN buffer group in use */
  2423.           OID             *oid;                   /* IN object we're inserting into */
  2424.           int             start;                  /* IN starting offset of delete */
  2425.           int             length;         /* IN amount of data being deleted */
  2426.  
  2427.  
  2428.           Sm_DeleteFromObject( ) deletes "length" bytes  of  data  from  an
  2429.           object,  beginning with the byte indicated by the offset "start".
  2430.           Sm_DeleteFromObject( ) is analogous to  sm_InsertObject( ).   All
  2431.           valid user descriptors affected by the deletion are, if possible,
  2432.           reset to point to the new  absolute  offset  within  the  object.
  2433.           There are two cases when this is not possible.
  2434.  
  2435.            (1)   The object's size is now smaller than the starting  offset
  2436.                  of  a  user  descriptor.   The "basePtr" field in the user
  2437.                  descriptor is set to NULL and the user descriptor is  made
  2438.                  invalid.    The   user  descriptor  must  be  released  by
  2439.                  sm_ReleaseObject( )  so  that   its   resources   can   be
  2440.                  reclaimed.
  2441.  
  2442.            (2)   The object's size is now smaller than  the  original  byte
  2443.                  range  addressable  by a user descriptor.  The size of the
  2444.                  range addressable by the descriptor is reduced to  reflect
  2445.                  the new size of the object.
  2446.  
  2447.           4.7.4.  Object Headers
  2448.  
  2449.  
  2450.           sm_ReadObjectHeader (groupIndex, oid, objHdr)
  2451.           int              groupIndex;            /* IN buffer group in use */
  2452.           OID             *oid;                   /* IN read this object's header */
  2453.           OBJHDR          *objHdr;                /* OUT place to put the header */
  2454.  
  2455.  
  2456.  
  2457.  
  2458.                                          35
  2459.  
  2460.  
  2461.  
  2462.  
  2463.  
  2464.  
  2465.  
  2466.  
  2467.  
  2468.  
  2469.           Sm_ReadObjectHeader( ) reads an object's header into  the  struc-
  2470.           ture  addressed  by "objHdr".  This function is the preferred one
  2471.           to use to determine if an object's identifier is valid.   If  the
  2472.           object's  identifier  is  invalid, Sm_ReadObjectHeader( ) returns
  2473.           esmFAILURE and puts esmBADOID in sm_errno.
  2474.  
  2475.  
  2476.           sm_SetObjectHeader (groupIndex, oid, objHdr)
  2477.           int              groupIndex;            /* IN buffer group in use */
  2478.           OID             *oid;                   /* IN set this object's header flags */
  2479.           OBJHDR          *objHdr;                /* IN the new header */
  2480.  
  2481.  
  2482.           Sm_SetObjectHeader( ) modifies  an  object's  header.   Only  the
  2483.           "tags" field is modified; the other fields are read-only.
  2484.  
  2485.           4.8.  Versions of Objects
  2486.  
  2487.           In order to allow efficient updating of shared data, the  Storage
  2488.           Manager  offers versions of objects.  Versions come in two kinds:
  2489.           working versions and frozen versions. A  working  version  of  an
  2490.           object  is  one  that can be modified.  Every object has at least
  2491.           one version, which is the object itself.  A working  version  may
  2492.           be frozen, after which it can no longer be modified.
  2493.  
  2494.           A new working version, called a descendent,  can  be  made  of  a
  2495.           frozen  object.  The descendent looks like a new object that is a
  2496.           copy of the frozen  object  from  which  it  came.   The  Storage
  2497.           Manager  determines  when it is necessary and efficient to make a
  2498.           copy of the frozen object, and makes the copy at that time.
  2499.  
  2500.  
  2501.           sm_CreateVersion (groupIndex, nearHint, parentObj, nearObj, oid)
  2502.           int              groupIndex;            /* IN buffer group to use */
  2503.           int              nearHint;              /* IN flag indicating where to create the new version near */
  2504.           OID             *parentObj;             /* IN object to create a version of */
  2505.           OID             *nearObj;               /* IN create the new version near this object */
  2506.           OID             *oid;                   /* OUT the new version's OID */
  2507.  
  2508.  
  2509.           Sm_CreateVersion( ) creates a new version of the  object  "paren-
  2510.           tObj" in the file containing "parentObj". The arguments "groupIn-
  2511.           dex",   "nearHint",   and    "nearObj"    are    used    as    in
  2512.           sm_CreateObject( ).  The  object identifier of the new version is
  2513.           returned in "oid". The object identified by "parentObj" must be a
  2514.           frozen  version.  The  new  version is a working version. The new
  2515.           version can be destroyed using sm_DestroyObject( ).  When  a  new
  2516.           version is created, the P_VERSIONED property is set in the object
  2517.           header.
  2518.  
  2519.           Like sm_CreateObject( ), sm_CreateVersion( ) does not leave  any-
  2520.           thing pinned in the buffer pool.
  2521.  
  2522.  
  2523.  
  2524.                                          36
  2525.  
  2526.  
  2527.  
  2528.  
  2529.  
  2530.  
  2531.  
  2532.  
  2533.  
  2534.  
  2535.           sm_FreezeVersion (groupIndex, oid)
  2536.           int              groupIndex;            /* IN buffer group to use */
  2537.           OID             *oid;                   /* IN object to be frozen */
  2538.  
  2539.  
  2540.           Sm_FreezeVersion( ) marks an object as frozen, preventing  subse-
  2541.           quent  modification  of the object, and allowing new working ver-
  2542.           sions to be made from this object.  When  an  object  is  frozen,
  2543.           both  the  P_VERSIONED and the P_FROZEN properties are set in the
  2544.           object header.  Once frozen, an object  cannot  be  unfrozen.   A
  2545.           frozen object can be destroyed.
  2546.  
  2547.           4.9.  Operations on Files
  2548.  
  2549.           A Storage Manager file is a flexible container in  which  objects
  2550.           are  place  when  they  are  created.  No object exists outside a
  2551.           file.
  2552.  
  2553.           The objects in a file can  be  scanned,  meaning  that  they  are
  2554.           visited exactly once.
  2555.  
  2556.           Files do not have preallocated  space  or  ownership  properties.
  2557.           Various consistency guarantees can be associated with files, with
  2558.           the effect that updating data in different  files  has  different
  2559.           costs.
  2560.  
  2561.           The Storage Manager offers operations for  creating,  destroying,
  2562.           scanning,  bulk-loading  files,  and for changing the consistency
  2563.           guarantees associated  with  files.   Some  operations  on  files
  2564.           acquire  locks on entire files.  The locks acquired are described
  2565.           in Appendix A.
  2566.  
  2567.           A file is identified by a unique  file  identifier  or  FID.  The
  2568.           Storage  Manager does not provide a way to find all files or file
  2569.           identifiers that exist, so it is left to the application to  keep
  2570.           track  of its file identifiers.  For example, consider an  appli-
  2571.           cation that embeds file identifiers in objects to create a  logi-
  2572.           cal  hierarchy  of  files.   The application had best destroy the
  2573.           files in a depth-first fashion, lest it lose  a  file  identifier
  2574.           before the file it identifies is destroyed.
  2575.  
  2576.           The following two macros can be used to give a file identifier an
  2577.           illegitimate initial value, and later to recognize that value:
  2578.  
  2579.               INVALIDATE_FID (FID fid)
  2580.  
  2581.           sets "fid" to an invalid file identifier.
  2582.  
  2583.               FID_IS_INVALID (FID fid)
  2584.  
  2585.           returns  TRUE  if  "fid"  is  the  invalid  identifier  given  by
  2586.           INVALIDATE_FID( ), FALSE otherwise.
  2587.  
  2588.  
  2589.  
  2590.                                          37
  2591.  
  2592.  
  2593.  
  2594.  
  2595.  
  2596.  
  2597.  
  2598.  
  2599.  
  2600.  
  2601.           The rest of this section describes operations on files and opera-
  2602.           tions that concern entire files of objects.
  2603.  
  2604.           4.9.1.  Consistency Guarantees for Files
  2605.  
  2606.           The log level of a file determines what level of  consistency  is
  2607.           maintained for the file in the event that a transaction aborts or
  2608.           a server crashes.  There are two log levels  for  files  on  data
  2609.           volumes:  LOG_ALL  and  LOG_SPACE.   LOG_ALL  indicates that con-
  2610.           sistency is maintained for user data  and  meta-data.   LOG_SPACE
  2611.           indicates  that  meta-data are guaranteed to be consistent.  This
  2612.           means that all objects  are  available  and  that  they  are  the
  2613.           correct  size,  but  their contents may be corrupted.  Files that
  2614.           have their log level set to LOG_SPACE are flushed when the  tran-
  2615.           saction  is committed. Data pages for large objects (objects that
  2616.           do not fit on a single disk page) may not be flushed, so there is
  2617.           no  guarantee  that  the  data is safely on disk until the server
  2618.           dismounts the volume.  The log level is not a permanent attribute
  2619.           of a file. When an application sets the log level for a file, the
  2620.           setting lasts until it is  changed  or  until  sm_ShutDown( )  is
  2621.           called.   If,  in  a  transaction,  the  log  level for a file is
  2622.           changed from LOG_SPACE to LOG_ALL, the Storage Manager guarantees
  2623.           only that the meta-data are consistent.
  2624.  
  2625.           LOG_ALL is the default log level for data  files.   LOG_SPACE  is
  2626.           designed to conserve log space and increase performance for those
  2627.           files whose data integrity is not critical. For example,  results
  2628.           of  a  query  may  be  stored in a file with its log level set to
  2629.           LOG_SPACE, since file can be  regenerated,  in  the  event  of  a
  2630.           failure.   To  conserve  log space when loading a large file, the
  2631.           log level for a file may be set to LOG_SPACE.  Once  the  loading
  2632.           transaction is committed, the log level should be set to LOG_ALL.
  2633.  
  2634.           Files on temporary volumes can have only one log level: LOG_NONE.
  2635.           See  Section 5.1.3, Temporary Volumes, for more information about
  2636.           temporary volumes.
  2637.  
  2638.           Sm_SetLogLevel( ) is used to change the log level for a  list  of
  2639.           files:
  2640.  
  2641.  
  2642.           sm_SetLogLevel (logLevel, fileCount, fids)
  2643.           int             logLevel;                       /* IN log level */
  2644.           int             fileCount;                      /* IN number of files to set level for */
  2645.           FID             fid[];                          /* IN list of files to set level for */
  2646.  
  2647.  
  2648.           The "logLevel" argument takes the values LOG_SPACE  and  LOG_ALL.
  2649.           The "fileCount" argument indicates the size of the last argument,
  2650.           "fid[]", which is a list of file identifiers of the  files  whose
  2651.           log  levels  are  to  be affected by this function.  It is not an
  2652.           error for a file in the list already to have the given log level.
  2653.  
  2654.  
  2655.  
  2656.                                          38
  2657.  
  2658.  
  2659.  
  2660.  
  2661.  
  2662.  
  2663.  
  2664.  
  2665.  
  2666.  
  2667.           If "fileCount" is zero, all files are given "logLevel".
  2668.  
  2669.           The volumes on which the  files  reside  must  be  available  for
  2670.           mounting,  and a side effect of setting the log level is that the
  2671.           volumes are mounted.
  2672.  
  2673.           Sm_SetLogLevel( ) has no effect on files that reside on temporary
  2674.           volumes (see Section 5.1.3, Temporary Volumes).
  2675.  
  2676.           sm_CreateFile (groupIndex, volid, fid)
  2677.           int              groupIndex;                    /* IN buffer group in use */
  2678.           VOLID    volid;                         /* IN the volume in which to place the file */
  2679.           FID             *fid;                           /* OUT the file ID of the new file */
  2680.  
  2681.  
  2682.           Sm_CreateFile( ) creates a new file on the  volume  indicated  by
  2683.           "volid".   The file identifier of the new file is returned in the
  2684.           structure to which "fid" points.  The caller is  responsible  for
  2685.           allocating space for the FID.
  2686.  
  2687.  
  2688.           sm_DestroyFile (groupIndex, fid)
  2689.           int              groupIndex;                    /* IN buffer group in use */
  2690.           FID             *fid;                           /* IN the file to destroy */
  2691.  
  2692.  
  2693.           Sm_DestroyFile( ) destroys the file  identified  by  "fid".   The
  2694.           objects  in  the  file  are  destroyed along with the file.  Disk
  2695.           space is released when the transaction is committed.
  2696.  
  2697.  
  2698.           sm_GetFirstOid (groupIndex, fid, oid, objHdr, emptyFlag)
  2699.           int              groupIndex;                    /* IN buffer group in use */
  2700.           FID             *fid;                           /* IN the file */
  2701.           OID             *oid;                           /* OUT first OID */
  2702.           OBJHDR          *objHdr;                        /* OUT the object's header */
  2703.           BOOL            *emptyFlag;                     /* OUT empty file flag */
  2704.  
  2705.  
  2706.           Sm_GetFirstOid( ) retrieves the object identifier and the  object
  2707.           header  of  the first object in the file designated by "fid". The
  2708.           first object is the first object on the first  physical  page  in
  2709.           the  file.  If the file does not contain any objects, "emptyFlag"
  2710.           is set to TRUE.
  2711.  
  2712.  
  2713.           sm_GetLastOid (groupIndex, fid, oid, objHdr, emptyFlag)
  2714.           int              groupIndex;                    /* IN buffer group in use */
  2715.           FID             *fid;                           /* IN the file */
  2716.           OID             *oid;                           /* OUT last OID */
  2717.           OBJHDR          *objHdr;                        /* OUT the object's header */
  2718.           BOOL            *emptyFlag;                     /* OUT empty file flag */
  2719.  
  2720.  
  2721.  
  2722.                                          39
  2723.  
  2724.  
  2725.  
  2726.  
  2727.  
  2728.  
  2729.  
  2730.  
  2731.  
  2732.  
  2733.           Sm_GetLastOid( ) retrieves the object identifier and  the  object
  2734.           header  of  the  last object in the file designated by "fid". The
  2735.           last object is the last object on the last physical page  in  the
  2736.           file.   If  the file does not contain any objects, "emptyFlag" is
  2737.           set to TRUE.
  2738.  
  2739.  
  2740.           sm_GetNextOid (groupIndex, baseOid, nextOid, objHdr, endMarker)
  2741.           int              groupIndex;                    /* IN buffer group in use */
  2742.           OID             *baseOid;                       /* IN next relative to this object */
  2743.           OID             *nextOid;                       /* OUT OID of the next object */
  2744.           OBJHDR          *objHdr;                        /* OUT the object's header */
  2745.           BOOL            *endMarker;                     /* OUT end-of-file flag */
  2746.  
  2747.  
  2748.           Sm_GetNextOid( ) retrieves the object identifier and  the  object
  2749.           header  of  the  next  object  in the file relative to the object
  2750.           addressed by "baseOid". "EndMarker" is set to TRUE  when  end-of-
  2751.           file  is  reached  (i.e.,  when  there  is  no  next  object  for
  2752.           sm_GetNextOid( ) to return).
  2753.  
  2754.           The next object is that which  resides  physically  next  in  the
  2755.           file.   There  is no way to scan a file's objects in the order in
  2756.           which they were inserted in the file.
  2757.  
  2758.           The preferred method for retrieving all the objects in a file  is
  2759.           to  use scans, described in the next sub-section.  Scans are more
  2760.           efficient than using sm_GetNextOid( ), which is present for back-
  2761.           ward compatibility.
  2762.  
  2763.  
  2764.           sm_GetPreviousOid (groupIndex, baseOid, prevOid, objHdr, endMarker)
  2765.           int              groupIndex;                    /* IN buffer group in use */
  2766.           OID             *baseOid;                       /* IN previous relative to this object */
  2767.           OID             *prevOid;                       /* OID of the previous object */
  2768.           OBJHDR          *objHdr;                        /* OUT the object's header */
  2769.           BOOL            *endMarker;                     /* OUT start-of-file flag */
  2770.  
  2771.  
  2772.           Sm_GetPreviousOid( ) retrieves the object identifier  and  object
  2773.           header  of the previous object in the file relative to the object
  2774.           addressed by "baseOid". "EndMarker" is set to  TRUE  when  start-
  2775.           of-file  is  reached  (i.e.,  when  there  is  no next object for
  2776.           sm_GetPreviousOid( ) to return).  Much like sm_GetNextOid( ), the
  2777.           previous  object is the object that is physically previous in the
  2778.           file.
  2779.  
  2780.           4.9.2.  Scanning Files
  2781.  
  2782.           The objects in a file can be visited most efficiently by scanning
  2783.           the file. During a scan, the client library locks the entire file
  2784.           so that while one application is using the file,  objects  cannot
  2785.  
  2786.  
  2787.  
  2788.                                          40
  2789.  
  2790.  
  2791.  
  2792.  
  2793.  
  2794.  
  2795.  
  2796.  
  2797.  
  2798.  
  2799.           be  inserted,  deleted,  or  changed  by another application. The
  2800.           Storage Manager does not support a single application's modifying
  2801.           a file during a scan.
  2802.  
  2803.           The client library also some information about the state  of  the
  2804.           scan  and  the structure of the file being scanned.  The informa-
  2805.           tion is stored in a scan descriptor, a structure  of  type  SCAN-
  2806.           DESC, which is meant to be treated as opaque by the application.
  2807.  
  2808.  
  2809.           sm_OpenScanWithGroup (fid, type, groupIndex, scanDesc, oid)
  2810.           FID             *fid;                           /* IN file to scan */
  2811.           int             type;                           /* IN type of scan -- UNUSED */
  2812.           int             groupIndex;                     /* IN buffer group for use in scan */
  2813.           SCANDESC        **scanDesc;                     /* OUT returned scan descriptor */
  2814.           OID             *oid;                           /* IN optional oid to begin scan -- UNUSED */
  2815.  
  2816.  
  2817.           Sm_OpenScanWithGroup( ) initializes a scan on the file  indicated
  2818.           by  "fid".   A  scan descriptor is passed back in "scanDesc", for
  2819.           use in subsequent scan calls. Using the  scan  mechanism  can  be
  2820.           considerably  more efficient that using the sm_GetNextOid( ) call
  2821.           or sm_ReadObject( ).  Scans use  a  buffer  group,  "groupIndex".
  2822.           This group should be created with the most-recently-used replace-
  2823.           ment policy, and its size should be tuned to reflect the  buffer-
  2824.           ing  requirements  for  the  scan. The buffer group should have a
  2825.           size of at least five pages.
  2826.  
  2827.           Objects are scanned in the order in which they physically  reside
  2828.           on disk.  After sm_OpenScanWithGroup( ) returns, the scan pointer
  2829.           is before the first object in the file.  This is true even if the
  2830.           file    is   empty,   in   which   case   the   first   call   to
  2831.           sm_ScanNextObject( ) returns a flag  indicating  the  end-of-file
  2832.           condition.   The  "type" and "oid" arguments are not used and are
  2833.           present for backward compatibility.
  2834.  
  2835.  
  2836.           sm_OpenScan (fid, type, groupSize, scanDesc, oid)
  2837.           FID             *fid;                           /* IN file to scan */
  2838.           int             type;                           /* IN type of scan -- UNUSED */
  2839.           int             groupSize;                      /* IN size of buffer group in pages */
  2840.           SCANDESC        **scanDesc;                     /* OUT returned scan descriptor */
  2841.           OID             *oid;                           /* IN optional oid to begin scan -- UNUSED */
  2842.  
  2843.  
  2844.           Sm_OpenScan( ) is like sm_OpenScanWithGroup( ), but  it  is  less
  2845.           flexible,  and  it  is provided for backward compatibility. It is
  2846.           identical to sm_OpenScanWithGroup( ) except  that  it  creates  a
  2847.           buffer  group  with the most-recently-used replacement policy and
  2848.           size "groupSize". "GroupSize" should be at  least  five  (pages).
  2849.           The buffer group is destroyed when the scan is closed.
  2850.  
  2851.  
  2852.  
  2853.  
  2854.                                          41
  2855.  
  2856.  
  2857.  
  2858.  
  2859.  
  2860.  
  2861.  
  2862.  
  2863.  
  2864.  
  2865.           sm_ScanNextObject (scanDesc, start, length, retDesc, eof)
  2866.           SCANDESC        *scanDesc;                      /* IN scan descriptor */
  2867.           int             start;                          /* IN starting offset in object */
  2868.           int             length;                 /* IN number of bytes to read */
  2869.           USERDESC        **retDesc;                      /* OUT descriptor to access the data */
  2870.           BOOL            *eof;                           /* OUT end of file indicator */
  2871.  
  2872.  
  2873.           sm_ScanNextObject( ) reads the next object in the file  and  pins
  2874.           the  object  as if sm_ReadObject( ) were used.  "ScanDesc" is the
  2875.           scan descriptor returned when the scan was  opened.   "Start"  is
  2876.           the starting offset within the object to return.
  2877.  
  2878.           "Length" is the length of the object read to perform. If "length"
  2879.           is READ_ALL, the entire object is read (assuming that the size of
  2880.           the entire object is not greater  than  the  amount  of  unpinned
  2881.           space  in  the buffer group). To obtain the object header and OID
  2882.           information for the object, use a "length" of zero.
  2883.  
  2884.           sm_ScanNextObject( ) returns a user descriptor for the object, if
  2885.           there  is one to pin, whether or not any bytes are pinned.  "Eof"
  2886.           is set to TRUE and "retDesc" is set to NULL  when  there  are  no
  2887.           more  objects  to  be scanned.  Each call to sm_ScanNextObject( )
  2888.           releases the user descriptor returned by the previous scan  call,
  2889.           so  sm_ReleaseObject( ) must not be used on user descriptors that
  2890.           are acquired by scanning files.
  2891.  
  2892.  
  2893.           sm_ScanNextBytes (scanDesc, length)
  2894.           SCANDESC        *scanDesc;                      /* IN scan descriptor */
  2895.           int             length;                 /* IN number of bytes to read */
  2896.  
  2897.  
  2898.           Sm_ScanNextBytes( ) is useful when a file being scanned  contains
  2899.           very  large  objects  that cannot be expected to fit in memory. A
  2900.           sm_ScanNextObject( ) call can be made  with  a  relatively  small
  2901.           length   to   read   in   the   first   section   of  an  object.
  2902.           Sm_ScanNextBytes( ) is used subsequently to iterate over the rest
  2903.           of that object, with each call reading in the next "length" bytes
  2904.           of the current scan object.  The iteration can be  controlled  by
  2905.           observing  the  objectSize  field of the user descriptor.  esmEN-
  2906.           DOFOBJECT is returned if there are no more bytes to  be  read  in
  2907.           the current object.
  2908.  
  2909.  
  2910.           sm_CloseScan (scanDesc)
  2911.           SCANDESC        *scanDesc;                      /* IN scan descriptor */
  2912.  
  2913.  
  2914.           Sm_CloseScan( ) closes the scan associated with  "scanDesc".   It
  2915.           releases  the  scan  descriptor and the user descriptors and data
  2916.           pinned during the scan.
  2917.  
  2918.  
  2919.  
  2920.                                          42
  2921.  
  2922.  
  2923.  
  2924.  
  2925.  
  2926.  
  2927.  
  2928.  
  2929.  
  2930.  
  2931.           4.9.3.  Bulk-loading Files
  2932.  
  2933.           WARNING: the file bulk load facility does not  work  properly  in
  2934.           version 3.1.  We recommend that it not be used.
  2935.  
  2936.  
  2937.           sm_OpenLoad (fid, type, groupSize, fillFactor, loadDesc)
  2938.           FID             *fid;                           /* IN file to scan */
  2939.           int             groupSize;                      /* IN size of load buffer group */
  2940.           float           fillFactor;                     /* IN fill percentage */
  2941.           LOADDESC        **loadDesc;                     /* OUT returned load descriptor */
  2942.  
  2943.  
  2944.           Sm_OpenLoad( ) prepares to load a set of objects into a  file  in
  2945.           bulk.   Bulk  loading  a  file can be more efficient than using a
  2946.           series of  sm_CreateObject( )  calls.   The  file,  indicated  by
  2947.           "fid",   need  not  be  empty,  in which case the new objects are
  2948.           added to the end of the file. The load mechanism creates and uses
  2949.           its  own  buffer  group;  the size of the buffer group is "group-
  2950.           Size".  The "fillFactor" argument is ignored; it is  present  for
  2951.           future extensions.  A load descriptor, "loadDesc" is returned for
  2952.           use  in  subsequent   operations   (   sm_LoadNextObject( )   and
  2953.           sm_CloseLoad( )).
  2954.  
  2955.  
  2956.           sm_LoadNextObject (loadDesc, length, data, oid)
  2957.           LOADDESC        *loadDesc;                      /* IN load descriptor */
  2958.           int             length;                 /* IN length of the object */
  2959.           void            *data;                          /* IN the object's data */
  2960.           OID             *oid;                           /* OUT returned new object id */
  2961.  
  2962.  
  2963.           Sm_LoadNextObject( ) creates a new object if size "length" in the
  2964.           file  for which the "loadDesc" was opened. The new object is ini-
  2965.           tialized with "data". If "data" is NULL,  the  object  is  filled
  2966.           with  zeroes.   Sm_LoadNextObject( ) returns an object identifier
  2967.           for the new object in "oid".
  2968.  
  2969.  
  2970.           sm_CloseLoad (loadDesc)
  2971.           LOADDESC        *loadDesc;                      /* IN load to close */
  2972.  
  2973.  
  2974.           Sm_CloseLoad( ) ends the bulk-load operation.
  2975.  
  2976.           4.10.  Operations on Indexes
  2977.  
  2978.           The Storage Manager's index facility associates keys with  fixed-
  2979.           length  elements.  The keys can be any basic C data type (SM_int,
  2980.           SM_long, SM_short, SM_float, SM_double) or  strings  (SM_string).
  2981.           The size of the element is fixed when the index is created.
  2982.  
  2983.  
  2984.  
  2985.  
  2986.                                          43
  2987.  
  2988.  
  2989.  
  2990.  
  2991.  
  2992.  
  2993.  
  2994.  
  2995.  
  2996.  
  2997.           B[+]tree index and linear  hashing  index  functions  are  imple-
  2998.           mented.  B[+]tree  provides  fast  index  lookup  on all kinds of
  2999.           queries, especially range queries. Linear hashing  provides  even
  3000.           faster  index lookup and supports linear space growth for dynami-
  3001.           cally growing indexes, but it supports only exact-match  queries.
  3002.           More information about linear hashing can be found in [Litw88].
  3003.  
  3004.           A key is fully described by the KEY structure:
  3005.  
  3006.  
  3007.           typedef struct {
  3008.                   TWO     length; /* length of the key */
  3009.                   void*   valuePtr;       /* pointer to value of the key */
  3010.           } KEY;
  3011.  
  3012.  
  3013.           Index keys are compared according to the key type given when  the
  3014.           index  is  created.   The key type determines the number of bytes
  3015.           considered in a key comparison.  In the case  of  keys  that  are
  3016.           strings,  the length fields in the keys in question determine the
  3017.           number of bytes compared.  Strings are compared one character  at
  3018.           a  time.   The  client  library  does  not terminate strings with
  3019.           nulls.  When two strings of different lengths are  compared,  the
  3020.           shorter  string  is  compared with the corresponding substring of
  3021.           the longer string.  If the shorter string and  the  corresponding
  3022.           substring  are  equal,  the longer string is considered to be the
  3023.           larger of the two.  This means that "abc " is longer than "abc".
  3024.  
  3025.           Characters are compared as ASCII values.
  3026.  
  3027.           4.10.1.  Creating and Destroying Indexes
  3028.  
  3029.           When an index is created, the client library creates a handle, by
  3030.           which the index is identified in subsequent operations.  The han-
  3031.           dle is an index identifier, a structure of type IID.   The  value
  3032.           of  the index identifier can be treated as an opaque value by the
  3033.           application.
  3034.  
  3035.           The following macros can be used it give an illegitimate  initial
  3036.           value to an index identifier, and later to recognize that value:
  3037.  
  3038.               INVALIDATE_IID (IID iid)
  3039.  
  3040.           sets "iid" to an invalid index identifier.
  3041.  
  3042.               IID_IS_INVALID (IID iid)
  3043.  
  3044.           returns TRUE if "iid" has the value given  by  INVALIDATE_IID( ),
  3045.           FALSE if not.
  3046.  
  3047.           The rest of this section describes the functions that operate  on
  3048.           indexes.
  3049.  
  3050.  
  3051.  
  3052.                                          44
  3053.  
  3054.  
  3055.  
  3056.  
  3057.  
  3058.  
  3059.  
  3060.  
  3061.  
  3062.  
  3063.           sm_CreateIndex(volume, groupIndex, ndxType, keyType, maxKeyLen, elSize, unique, ndx)
  3064.           VOLID           volume;         /* IN volume on which index is to be built */
  3065.           int                     groupIndex;             /* IN the buffer group to use */
  3066.           SMTYPE          ndxType;                /* IN SM_BTREENDX, SM_HASHNDX, etc */
  3067.           SMDATATYPE      keyType;                /* IN SM_int, SM_long, SM_string, etc */
  3068.           int                     maxKeyLen;              /* IN maximum key length of a key in the index */
  3069.           int                     elSize;                 /* IN element size (mpl of 4, < SM_MAXELEMLEN) */
  3070.           BOOL                    unique;         /* IN TRUE if key is unique */
  3071.           IID*                    ndx;                    /* OUT returned index identifier */
  3072.  
  3073.  
  3074.           Sm_CreateIndex( ) creates an index that resides on "volume".  [3]
  3075.           "NdxType"  specifies  the type of index (SM_BTREENDX for B[+]tree
  3076.           or SM_HASHNDX for linear hashing).  "KeyType" indicates the  data
  3077.           type  of  the  key.   The maximum length of a key in the index is
  3078.           given in "maxKeyLen". The size of the elements in  the  index  is
  3079.           given  in  "elSize". The element size  must be a multiple of four
  3080.           and less than SM_MAXELEMLEN (20). If "unique" is FALSE, the index
  3081.           is  able to store multiple elements under the same key.  An index
  3082.           identifier is returned in "ndx" upon successful completion.
  3083.  
  3084.  
  3085.           sm_DestroyIndex(ndx, groupIndex)
  3086.           IID*                    ndx;                    /* IN id of index to destroy */
  3087.           int                     groupIndex;             /* IN which buffer group to use */
  3088.  
  3089.  
  3090.           Sm_DestroyIndex( ) destroys the index associated with "ndx".
  3091.  
  3092.  
  3093.           sm_SetLHashLoadThreshold(ndx, groupIndex, load)
  3094.           IID*                    ndx;                    /* IN index identifier */
  3095.           int                     groupIndex;             /* IN which buffer group to use */
  3096.           float                   loadFactor;             /* IN the load factor to use for linear hashing */
  3097.  
  3098.  
  3099.           Sm_SetLHashLoadThreshold( ) changes the load factor for a  linear
  3100.           hashing  index  from  the  default 75% to the given "loadFactor".
  3101.           The default load factor, 75%, yields the  best  access  time  and
  3102.           space  utilization.   See  [Litw88]  for information about linear
  3103.           hashing and when it might be useful to change  the  load  factor.
  3104.           The load factor can be set only on a newly created index.
  3105.  
  3106.  
  3107.  
  3108.           ____________________
  3109.              [3]  Indexes  on  temporary  volumes  are   not   implemented.
  3110.           (Section  5.1.3,  Temporary  Volumes).   If  the  volume given is
  3111.           temporary, sm_CreateIndex( ) returns esmFAILURE, with error  code
  3112.           esmNOTIMPLEMENTED.
  3113.  
  3114.  
  3115.  
  3116.  
  3117.  
  3118.                                          45
  3119.  
  3120.  
  3121.  
  3122.  
  3123.  
  3124.  
  3125.  
  3126.  
  3127.  
  3128.  
  3129.           4.10.2.  Inserting and Removing Index Elements
  3130.  
  3131.  
  3132.           sm_InsertEntry(ndx, groupIndex, key, elem)
  3133.           IID*                    ndx;                    /* IN index identifier */
  3134.           int                     groupIndex;             /* IN which buffer group to use */
  3135.           KEY*                    key;                    /* IN key to insert */
  3136.           void*                   elem;                   /* IN element associated with key */
  3137.  
  3138.  
  3139.           Sm_InsertEntry( ) inserts a  <key,  elem>  pair  into  the  index
  3140.           "ndx".  If  "ndx"  is  a  unique index and the key to be inserted
  3141.           already appears in the index, sm_InsertEntry( ) returns an  error
  3142.           in  sm_errno.   If  the index is not unique, there is no limit to
  3143.           the number of duplicate keys as long as  different  elements  are
  3144.           associated with them.
  3145.  
  3146.  
  3147.           sm_RemoveEntry(ndx, groupIndex, key, elem)
  3148.           IID*                    ndx;                    /* IN index identifier */
  3149.           int                     groupIndex;             /* IN which buffer group to use */
  3150.           KEY*                    key;                    /* IN key to remove */
  3151.           void*                   elem;                   /* IN element associated with key */
  3152.  
  3153.  
  3154.           Sm_RemoveEntry( ) removes a  <key,  elem>  pair  from  the  index
  3155.           "ndx".
  3156.  
  3157.           4.10.3.  Loading Indexes in Bulk
  3158.  
  3159.           The Storage Manager provides a bulk-load facility for efficiently
  3160.           loading  an empty index.  When the application begins a bulk-load
  3161.           operation, the client library allocates a  temporary  run-buffer,
  3162.           which  is used for sorting runs. Henceforth, the application uses
  3163.           sm_InsertEntry( ) repeatedly to  load  elements  into  index;  no
  3164.           other  index  operations  are  allowed  during  a bulk-load. Each
  3165.           sm_InsertEntry( ) operation for the index inserts a  <key,  elem>
  3166.           pair  into the temporary run buffer. The run buffer is sorted and
  3167.           written to the work file as a "sorted-run" when it is full.  When
  3168.           the  application  terminates  the bulk-load operation, the client
  3169.           library merges the sorted-runs into a sorted stream,  from  which
  3170.           the index is built from the bottom, up.
  3171.  
  3172.           Entries cannot be removed during a bulk-load operation.
  3173.  
  3174.  
  3175.  
  3176.           int sm_BeginIndexLoad(ndx, groupIndex, workVolume, runSize)
  3177.           IID*                    ndx;                    /* IN index identifier */
  3178.           int                     groupIndex;             /* IN the buffer group to use */
  3179.           VOLID           workVolume;             /* IN work volume */
  3180.           int                     runSize;                /* IN size of each sorted run in pages */
  3181.  
  3182.  
  3183.  
  3184.                                          46
  3185.  
  3186.  
  3187.  
  3188.  
  3189.  
  3190.  
  3191.  
  3192.  
  3193.  
  3194.  
  3195.           Sm_BeginIndexLoad( ) prepares to load the index given  in  "ndx",
  3196.           using  the  buffer group "groupIndex".  Sm_BeginIndexLoad( ) uses
  3197.           the volume named by "workVolume" for the  sorted  runs.  Using  a
  3198.           temporary  volume for the work volume yields the best performance
  3199.           (see Section 5.1.3, Temporary Volumes).
  3200.  
  3201.           The "runSize" argument determines how many MIN_PAGESIZE pages  to
  3202.           fill  before  ending a run. The larger "runSize", the more memory
  3203.           is consumed by the bulk-load, with a commensurate improvement  in
  3204.           speed.   Sm_BeginIndexLoad( ),  if it is used,  must be the first
  3205.           operation performed on an index.
  3206.  
  3207.  
  3208.  
  3209.           int sm_EndIndexLoad(ndx)
  3210.           IID*                    ndx;                    /* IN index identifier */
  3211.  
  3212.           Sm_EndIndexLoad( ) concludes the bulk-load and builds the index.
  3213.  
  3214.  
  3215.           int sm_AbortIndexLoad(ndx)
  3216.           IID*                    ndx;                    /* IN index identifier */
  3217.  
  3218.           sm_AbortIndexLoad( ) aborts the bulk-loading  of  an  index.  All
  3219.           resources used by the index are freed.
  3220.  
  3221.           4.10.4.  Scanning Indexes
  3222.  
  3223.           Indexes are used  by  posing  queries  with  the  sm_FetchInit( )
  3224.           operation. A query requests all the elements whose key values lie
  3225.           in a range.  The results of the query are fetched, one element at
  3226.           a time, with the sm_FetchNext( ) operation.  An index scan uses a
  3227.           cursor, a value of the type SMCURSOR.  A cursor can be treated by
  3228.           the  application  as  an  opaque value.  The following two macros
  3229.           give a cursor an invalid initial value and recognize that value:
  3230.  
  3231.               INVALIDATE_CURSOR (SMCURSOR cursor)
  3232.  
  3233.           sets "cursor" to an invalid index scan cursor.
  3234.  
  3235.               CURSOR_IS_INVALID (SMCURSOR cursor)
  3236.  
  3237.           returns   TRUE   if   "cursor"   is   the    value    given    by
  3238.           INVALIDATE_CURSOR( ), FALSE if not.
  3239.  
  3240.           The rest of this section describes the  functions  used  to  scan
  3241.           indexes.
  3242.  
  3243.  
  3244.  
  3245.  
  3246.  
  3247.  
  3248.  
  3249.  
  3250.                                          47
  3251.  
  3252.  
  3253.  
  3254.  
  3255.  
  3256.  
  3257.  
  3258.  
  3259.  
  3260.  
  3261.           sm_FetchInit(ndx, groupIndex, bound1, cond1, bound2, cond2, cursor)
  3262.           IID*                    ndx;                    /* IN index identifier */
  3263.           int                     groupIndex;             /* IN which buffer group to use */
  3264.           KEY*                    bound1;         /* IN starting bound of the scan */
  3265.           SMCOND          cond1;                  /* IN starting condition */
  3266.           KEY*                    bound2;         /* IN ending bound of the scan */
  3267.           SMCOND          cond2;                  /* IN ending condition */
  3268.           SMCURSOR*       cursor;         /* OUT returned pointer if non-NULL */
  3269.  
  3270.  
  3271.           Sm_FetchInit( ) begins a scan on the index "ndx".  The  arguments
  3272.           "bound1"  and  "cond1"  specify  the  beginning search condition.
  3273.           "Bound2" and "cond2" specify the  ending  search  condition.  The
  3274.           conditions  can  be   SM_EQ,  SM_G, SM_L, SM_GEQ, or SM_LEQ.  The
  3275.           "cursor" argument is initialized by sm_FetchInit( ) and  used  by
  3276.           sm_FetchNext( ).   The  caller  is responsible for allocating the
  3277.           space for the cursor and the client library  is  responsible  for
  3278.           the value of the cursor.
  3279.  
  3280.           The direction of the scan (ascending or descending) is determined
  3281.           by  the bounds and conditions of the query. The beginning and end
  3282.           of an index are specified with the macros SM_BOF and SM_EOF.  For
  3283.           linear  hashing  indexes (type SM_HASHNDX), the value that can be
  3284.           used for "cond1" and "cond2" is SM_EQ.
  3285.  
  3286.           Several examples of queries follow:
  3287.  
  3288.            (1)   Scan from key1 = "10" to key2 = "30" inclusively:
  3289.                  sm_FetchInit( ..., key1, SM_GEQ, key2, SM_LEQ, cursor) ---
  3290.                  ascending
  3291.                  sm_FetchInit( ..., key2, SM_LEQ, key1, SM_GEQ, cursor) ---
  3292.                  descending
  3293.  
  3294.  
  3295.            (2)   Scan from key1 = "10" to the end of the index:
  3296.                  sm_FetchInit(  ...,  key1,  SM_GEQ,  SM_EOF,  cursor)  ---
  3297.                  ascending
  3298.                  sm_FetchInit( ..., SM_EOF, key1, SM_GEQ, cursor) ---  des-
  3299.                  cending
  3300.  
  3301.  
  3302.            (3)   Scan the whole index:
  3303.                  sm_FetchInit( ..., SM_BOF, SM_EOF, cursor) --- ascending
  3304.                  sm_FetchInit( ..., SM_EOF, SM_BOF, cursor) --- descending
  3305.  
  3306.           sm_FetchNext(cursor, retKey, retElem, eof)
  3307.           SMCURSOR*       cursor;         /* IN cursor from sm_Fetch( ) */
  3308.           KEY*                    retKey;         /* OUT returned key (optional) */
  3309.           void*                   retElem;                /* OUT elem */
  3310.           BOOL*           eof;                    /* OUT to TRUE if EOF reached */
  3311.  
  3312.  
  3313.  
  3314.  
  3315.  
  3316.                                          48
  3317.  
  3318.  
  3319.  
  3320.  
  3321.  
  3322.  
  3323.  
  3324.  
  3325.  
  3326.  
  3327.           Sm_FetchNext( ) fetches the next element  returned  by  a  query.
  3328.           The  element is returned in the structure addressed by "retElem".
  3329.           A copy of the key can also be returned to the caller.   If  "ret-
  3330.           Key"  is  NULL,  no key is returned.  If "retKey" points to a key
  3331.           structure, the key is returned in that structure.   The  "length"
  3332.           field  in  the key structure must indicate amount of space avail-
  3333.           able in the target of the "valuePtr" field.  This must be  enough
  3334.           for  the  longest key in the index. The caller is responsible for
  3335.           allocating space for "retKey" and "retElem".
  3336.  
  3337.           sm_FetchNext( ) returns FALSE in "eof" if an element is returned.
  3338.           If  there  are  no  more elements that satisfy the query, TRUE is
  3339.           returned in "eof".
  3340.  
  3341.  
  3342.           4.11.  Advanced Topics
  3343.  
  3344.           4.11.1.  External Two-Phase Commit Functions
  3345.  
  3346.           The Storage Manager can particpate in transactions coordinated by
  3347.           other   software   modules   that  employ  the  two-phase  commit
  3348.           "presumed abort" transaction semantics and  protocol.   (For  the
  3349.           purpose  of  this  section,  the reader is assumed to be familiar
  3350.           with the "presumed abort" protocol.)  The coordinator in  such  a
  3351.           situation  is  external  to the Storage Manager; it is assumed to
  3352.           have its own stable storage, and it is assumed  to  recover  from
  3353.           failures  in  a short time (the precise meaning of which is given
  3354.           forthwith).
  3355.  
  3356.           A prepared transaction, like an active transaction, consumes  log
  3357.           space  on  one or more Exodus servers, beginning at a fixed loca-
  3358.           tion in each log.  A Storage Manager server's log is like a  cir-
  3359.           cular  buffer;  it wraps and reuses the beginning of the log.  If
  3360.           long-running or prepared transactions are still  in  the  system,
  3361.           the  server  eventually tries to re-use log space consumed by the
  3362.           oldest transaction, at which point it effectively runs out of log
  3363.           space.   A  coordinator  must  resolve  its prepared transactions
  3364.           before the servers run out of log  space.   The  amount  of  time
  3365.           involved  is a function of the size of the log on the participat-
  3366.           ing servers and the load on those servers.
  3367.  
  3368.           For the purpose of this discussion, the portion of a global tran-
  3369.           saction that involves a single Exodus Storage Manager transaction
  3370.           is called a thread of the global transaction.  Each  thread  has,
  3371.           in  addition  to its local transaction identifier, a global tran-
  3372.           saction identifier.  Global transaction identifiers are  provided
  3373.           by  the  application  or  some  external  authority,  and must be
  3374.           unique.  A global transaction identifier has type  GTID,  defined
  3375.           in sm_client.h, as follows:
  3376.  
  3377.  
  3378.  
  3379.  
  3380.  
  3381.  
  3382.                                          49
  3383.  
  3384.  
  3385.  
  3386.  
  3387.  
  3388.  
  3389.  
  3390.  
  3391.  
  3392.  
  3393.               #define MAXOPAQUELEN 255
  3394.               typedef struct {
  3395.                      int              length;     /* maximum MAXOPAQUELEN bytes */
  3396.                      u_char   opaque[MAXOPAQUELEN];
  3397.               } GTID;
  3398.  
  3399.  
  3400.           The Storage Manager does not interpret the contents of the opaque
  3401.           part of the global transaction identifier.
  3402.  
  3403.           An application that invokes the external two-phase commit  proto-
  3404.           col can find itself in any of the transaction states mentioned in
  3405.           Section 4.3.2 ("Transaction States").  It can also find itself in
  3406.           the  PREPARED state after a call to sm_PrepareTransaction( ).  An
  3407.           application in PREPARED state  calls  sm_CommitTransaction( )  or
  3408.           sm_AbortTransaction( )  to complete the transaction and return to
  3409.           the INACTIVE state.
  3410.  
  3411.           While the coordinator for a global transaction is external to the
  3412.           Storage Manager, a single Storage Manager server corresponds with
  3413.           the client library and coordinates the  Storage  Manager  servers
  3414.           that  participate in the thread.  If the application should crash
  3415.           during a two-phase commit, a new application program  (represent-
  3416.           ing  the  global  coordinator)  must run, and it must contact the
  3417.           Storage Manager that is acting as the thread's  coordinator.   In
  3418.           order  to  locate  the  proper server, a two-phase commit process
  3419.           begins by informing the client library that a  transaction  is  a
  3420.           thread  of  a global transaction, and by identifying the thread's
  3421.           coordinator.   The  function  sm_Enter2PC( ),  described   below,
  3422.           accomplishes this.
  3423.  
  3424.  
  3425.           sm_Enter2PC (tid, gtid, handle)
  3426.           TID             tid;                    /* IN transaction ID */
  3427.           GTID            *gtid;                  /* IN global transaction ID */
  3428.           COORD_HANDLE    *handle;        /* OUT for use if client crashes */
  3429.  
  3430.  
  3431.  
  3432.           The application supplies the local and global  transaction  iden-
  3433.           tifiers.  The client library identifies a thread coordinator, and
  3434.           produces a handle for the application to write to stable storage.
  3435.           The  handle  identifies  the  thread  coordinator;  it is used by
  3436.           sm_Recover2PC( ) if the client crashes before the two-phase  com-
  3437.           mit is completed.
  3438.  
  3439.           The handle must be written to stable  storage  before  the  first
  3440.           phase of the commit begins, otherwise the application and Storage
  3441.           Manager may not be able to recover from a subsequent  application
  3442.           failure.
  3443.  
  3444.  
  3445.  
  3446.  
  3447.  
  3448.                                          50
  3449.  
  3450.  
  3451.  
  3452.  
  3453.  
  3454.  
  3455.  
  3456.  
  3457.  
  3458.  
  3459.           sm_PrepareTransaction (tid, vote)
  3460.           TID             tid;                    /* IN transaction ID */
  3461.           VOTE            *vote;                  /* OUT result of first phase */
  3462.  
  3463.  
  3464.  
  3465.           The  application  calls  sm_PrepareTransaction( )  to  begin  the
  3466.           first,    or    prepare,    phase    of   a   two-phase   commit.
  3467.           sm_PrepareTransaction( ) determines if the participating  servers
  3468.           are  able  to commit the transaction, and directs them to prepare
  3469.           to commit if they are.  If any of the  participating  servers  is
  3470.           unable  to  commit  the transaction, the vote returned is NOVOTE,
  3471.           sm_PrepareTransaction( )  sets   sm_error   to   esmTRANSABORTED,
  3472.           sm_reason  to  esmTRANSNOTPREPARED,  and  returns esmFAILURE; the
  3473.           application must call sm_AbortTransaction( ).
  3474.  
  3475.           If all participating servers are able to commit, and any of  them
  3476.           logged  updates  during the transaction, the vote is YESVOTE, and
  3477.           the transaction state becomes PREPARED.  If the  transaction  did
  3478.           not  update any data on any of the servers, the vote is READVOTE,
  3479.           and     the     transaction     state      becomes      INACTIVE.
  3480.           Sm_PrepareTransaction( )  returns  esmNOERROR  if the transaction
  3481.           becomes prepared (all servers vote  YESVOTE)  or  committed  (all
  3482.           server vote READVOTE).
  3483.  
  3484.           If    an    error    occurs    during    the    prepare    phase,
  3485.           sm_PrepareTransaction( ) returns esmFAILURE.  If it is a recover-
  3486.           able error, the client library returns an error code specific  to
  3487.           the  error  in  sm_errno (such as esmTRANSDISABLED if a server is
  3488.           performing recovery), and the application can try again  to  call
  3489.           sm_PrepareTransaction( ).   Some errors, on the other hand, cause
  3490.           the    transaction    to    be    aborted,    in    which    case
  3491.           sm_PrepareTransaction( ) returns esmTRANSABORTED in sm_errno, and
  3492.           a vote of NOVOTE.
  3493.  
  3494.           If an application crashes during the first phase, the application
  3495.           must retry the prepare phase and complete the transaction.  If it
  3496.           does not retry the prepare phase, and the transaction was  indeed
  3497.           prepared before the application crashed, the prepared transaction
  3498.           consumes resources indefinitely, and eventually its servers  will
  3499.           run out of log space.
  3500.  
  3501.           Once a transaction is prepared, an application  must  invoke  the
  3502.           second  phase  by aborting or committing the transaction (calling
  3503.           sm_AbortTransaction( ) or sm_CommitTransaction( ), respectively).
  3504.           It  is  an  error  to  commit a global transaction thread without
  3505.           first preparing the transaction, and it is an error  to  do  any-
  3506.           thing else without completing the second phase.
  3507.  
  3508.           When an error occurs during the  second  phase,  the  application
  3509.           cannot tell if the second phase completed (the transaction indeed
  3510.           committed or aborted). It is alway safe to try again to  complete
  3511.  
  3512.  
  3513.  
  3514.                                          51
  3515.  
  3516.  
  3517.  
  3518.  
  3519.  
  3520.  
  3521.  
  3522.  
  3523.  
  3524.  
  3525.           the    transaction    by    calling   sm_AbortTransaction( )   or
  3526.           sm_CommitTransaction( ) again.
  3527.  
  3528.           If the second phase fails because the network connection  between
  3529.           the  client  and  the thread coordinator breaks (esmSERVERDIED or
  3530.           esmNOTCONNECTED), the client must reconnect to the thread coordi-
  3531.           nator  before  the  second  phase can be finished.  The following
  3532.           function does that:
  3533.  
  3534.  
  3535.           sm_Continue2PC (tid, willing2block)
  3536.           TID             tid;                    /* IN transaction ID */
  3537.           BOOL            willling2block; /* IN ok to block indefinitely */
  3538.  
  3539.  
  3540.           If "willing2block" is TRUE, the client library  blocks  until  it
  3541.           connects to the thread coordinator.  If this is inappropriate for
  3542.           the application, "willing2block" must be FALSE,  and  the  client
  3543.           library tries once to contact the thread coordinator.
  3544.  
  3545.           If  the   application   crashes,   its   replacement   must   use
  3546.           sm_Recover2PC( ),  below, instead of sm_Continue2PC( ) to resolve
  3547.           the transaction.
  3548.  
  3549.  
  3550.           sm_Recover2PC (gtid, handle, willing2block, tid)
  3551.           COORD_HANDLE    *handle;                /* IN handle for thread coordinator */
  3552.           GTID                    *gtid;                  /* IN global transaction ID */
  3553.           BOOL                    willing2block;  /* IN ok to block indefinitely */
  3554.           TID                     *tid;                   /* OUT local transaction ID */
  3555.  
  3556.  
  3557.           When the application  crashes  (exits)  after  a  transaction  is
  3558.           prepared  but  before its second phase is completed, a "recovery"
  3559.           application program must be run within a short time to finish the
  3560.           two-phase  commit  and  resolve  the  transaction.  This recovery
  3561.           application must use sm_Recover2PC( ), supplying the global tran-
  3562.           saction  identifier and the handle returned by sm_Enter2PC( ) for
  3563.           that global transaction. The client library contacts  the  server
  3564.           identified in the handle, which conveys to the client library all
  3565.           that is needed for the application  to  enter  or  to  retry  the
  3566.           second  phase.  The transaction's local transaction identifier is
  3567.           returned by sm_Recover2PC( ) for the application to  use  in  its
  3568.           subsequent      call      to      sm_CommitTransaction( )      or
  3569.           sm_AbortTransaction( ).
  3570.  
  3571.           The thread coordinator may not be available, in  which  case  the
  3572.           client library keeps trying to connect or it will return an error
  3573.           (such   as   ECONNREFUSED),   depending   on   the    value    of
  3574.           "willing2block".  If "willing2block" is FALSE, the client library
  3575.           tries only once to connect the thread coordinator.
  3576.  
  3577.  
  3578.  
  3579.  
  3580.                                          52
  3581.  
  3582.  
  3583.  
  3584.  
  3585.  
  3586.  
  3587.  
  3588.  
  3589.  
  3590.  
  3591.           4.11.2.  Administrative Operations
  3592.  
  3593.           The following functions can be applied to one  or  more  servers.
  3594.           Each  function  takes  two arguments that determine which servers
  3595.           are of interest. The first argument is of type FLAGS,  and  takes
  3596.           one of the following values:
  3597.  
  3598.  
  3599.               VOL_ALL /* the servers for all volumes */
  3600.               VOL_USED_SINCE_INIT     /* servers for all volumes used */
  3601.               VOL_USED_IN_TRANSACTION /* servers used in this transaction  */
  3602.               VOL_BY_VOLID    /* the second argument applies */
  3603.  
  3604.           The client library keeps a list of volumes and the  servers  that
  3605.           manage  those  volumes.  The list is created from the information
  3606.           given in the configuration files and information  passed  to  the
  3607.           library  through  sm_SetClientOption( ), The flag VOL_ALL directs
  3608.           the client library to apply the administrative operation  to  the
  3609.           server  that  manages  each  volume in its list of known volumes.
  3610.           The flag VOL_USED_SINCE_INIT directs the client library to  apply
  3611.           the  administrative  operation  to  each  server  contacted since
  3612.           sm_Initialize( ) was called.   The  flag  VOL_USED_IN_TRANSACTION
  3613.           directs  the client library to apply the administrative operation
  3614.           to each server contacted so far for participation in the  current
  3615.           transaction.   (It  does not apply to servers to be contacted for
  3616.           the first time later in the transaction.)  The flag  VOL_BY_VOLID
  3617.           directs  the client library to apply the administrative operation
  3618.           to the server that manages the volume identified  by  the  second
  3619.           argument.   The  second  argument  is  a volume identifier VOLID,
  3620.           which  is  ignored  when   the   flags   argument   is   VOL_ALL,
  3621.           VOL_USED_SINCE_INIT,  or VOL_USED_IN_TRANSACTION.
  3622.  
  3623.           Ideally the administrative operations would only be performed  by
  3624.           trusted  clients, but the Storage Manager does not restrict their
  3625.           use.
  3626.  
  3627.  
  3628.           sm_TakeCheckpoint (flags,  volid, numCheckpoints)
  3629.           FLAGS           flags;                  /* IN which servers are of interest */
  3630.           VOLID           volid;                  /* IN which server is of interest */
  3631.           short                   numCheckpoints; /* IN number of checkpoints to take */
  3632.  
  3633.  
  3634.           Sm_TakeCheckpoint( ) sends a request to  the  server  to  take  a
  3635.           number  of checkpoints. In most circumstances, a value of one for
  3636.           the "numCheckpoints" argument is  appropriate.  A  value  greater
  3637.           than  1  can  be used to ensure that the server flushes all pages
  3638.           that were dirty when the first checkpoint  was  taken.  (This  is
  3639.           useful for experimenting with the recovery facility).
  3640.  
  3641.  
  3642.  
  3643.  
  3644.  
  3645.  
  3646.                                          53
  3647.  
  3648.  
  3649.  
  3650.  
  3651.  
  3652.  
  3653.  
  3654.  
  3655.  
  3656.  
  3657.           sm_ChangeCheckpointFrequency (flags, volid, frequency)
  3658.           FLAGS           flags;                  /* IN which servers are of interest */
  3659.           VOLID           volid;                  /* IN which server is of interest */
  3660.           int                     frequency;              /* IN number of log records between checkpoints */
  3661.  
  3662.  
  3663.           Sm_ChangeCheckpointFrequency( ) changes the frequency  of  check-
  3664.           points  taken by the server. The checkpoint frequency is based on
  3665.           the number of log pages written.  More information  about  check-
  3666.           point frequency can be found in Section 5.3, Tuning the Server.
  3667.  
  3668.  
  3669.           sm_ShutdownServer (flags, volid, options)
  3670.           FLAGS           flags;                  /* IN which servers are of interest */
  3671.           VOLID           volid;                  /* IN which server is of interest */
  3672.           FLAGS           options;                /* IN shutdown options */
  3673.  
  3674.  
  3675.           Sm_ShutdownServer( ) directs servers to shut down. The  "options"
  3676.           argument  indicates  what  a server should do before exiting. The
  3677.           following flags are  available:   NOFLAGS,  SHUT_TAKE_CHECKPOINT,
  3678.           SHUT_DUMP_CORE,        SHUT_ABORT_TRANS,       SHUT_COMMIT_TRANS,
  3679.           SHUT_CLEAN_VOLUMES. These can be combined with the  logical  "or"
  3680.           operator.
  3681.  
  3682.           If NOFLAGS is given, the server  kills  the  disk  processes  and
  3683.           exits.
  3684.  
  3685.           SHUT_TAKE_CHECKPOINT directs the  server  to  take  a  checkpoint
  3686.           before exiting.
  3687.  
  3688.           SHUT_DUMP_CORE directs the server to dump a core  file  debugging
  3689.           (see core(5)).
  3690.  
  3691.           SHUT_COMMIT_TRANS directs the server to wait  until  the  running
  3692.           transactions either commit or abort before it shuts down.
  3693.  
  3694.           SHUT_ABORT_TRANS directs the server to abort all running transac-
  3695.           tions   before   shutting   down.    When   SHUT_COMMIT_TRANS  or
  3696.           SHUT_ABORT_TRANS is used, clients cannot start any  new  transac-
  3697.           tions.
  3698.  
  3699.           SHUT_CLEAN_VOLUMES directs the server to  write  dirty  pages  to
  3700.           disk  before exiting.  To shut down a server after which recovery
  3701.           is    not    required,    use    either    SHUT_COMMIT_TRANS    |
  3702.           SHUT_CLEAN_VOLUMES or SHUT_ABORT_TRANS | SHUT_CLEAN_VOLUMES.
  3703.  
  3704.  
  3705.  
  3706.  
  3707.  
  3708.  
  3709.  
  3710.  
  3711.  
  3712.                                          54
  3713.  
  3714.  
  3715.  
  3716.  
  3717.  
  3718.  
  3719.  
  3720.  
  3721.  
  3722.  
  3723.           sm_ServerStatistics (flags, volid, numServers, stats, reset)
  3724.           FLAGS           flags;                  /* IN which servers are of interest */
  3725.           VOLID           volid;                  /* IN which server is of interest */
  3726.           int                     *numServers;    /* OUT # servers contacted */
  3727.           SERVERSTATS     **stats;                /* OUT servers' statistics */
  3728.           BOOL                    reset;                  /* IN TRUE = reinitialize counters */
  3729.  
  3730.  
  3731.           Sm_ServerStatistics( )  obtains  statistics  about  one  or  more
  3732.           servers.  For  each  server  contacted,  a  set  of statistics is
  3733.           returned.  The client library allocates space for the statistics,
  3734.           and  the  application is responsible for freeing that space ( see
  3735.           the manual page for malloc(3)  ).   The  "flags"  indicate  which
  3736.           servers  are  of interest, and the number of servers contacted is
  3737.           returned     in     "*numServers".       On      return      from
  3738.           sm_ServerStatistics( ),  the  "*stats" pointer addresses an array
  3739.           of "*numServers" SERVERSTATS  structures.   This  array  must  be
  3740.           freed by the application with one call to free(3).
  3741.  
  3742.           If "reset" is TRUE, the statistics labeled as counters below  are
  3743.           reset to zero.
  3744.  
  3745.           The SERVERSTATS structure looks like this:
  3746.  
  3747.               typedef struct {
  3748.                      int              numClients;             /* # clients connected */
  3749.                      int              numTrans;               /* # transactions in progress */
  3750.                      int              numVolumes;             /* # volumes mounted */
  3751.                      int              freeLogSpace;   /* approximate # bytes free log space */
  3752.                      int              chpntFreq;              /* checkpoint frequency */
  3753.                      int              totalCommits;   /* # transactions committed */
  3754.                      int              totalAborts;            /* # transactions aborted */
  3755.                      int              diskReads;              /* # disk reads */
  3756.                      int              diskWrites;             /* # disk writes */
  3757.                      MESSAGESTATS     msgStats;       /* server's message counters */
  3758.               } SERVERSTATS;
  3759.  
  3760.  
  3761.           The MESSAGESTATS structure contains statistics about the  client-
  3762.           server  protocol  and the server-server protocol.  A set of these
  3763.           statistics is kept by the client library a set is  kept  by  each
  3764.           server.   The client library's statistics are found in the global
  3765.           structure
  3766.  
  3767.           extern MESSAGESTATS MsgStats;
  3768.  
  3769.           The MESSAGESTATS structure contains the  following  counters  for
  3770.           each  message  type:  messages  sent,  messages received, replies
  3771.           received with an  error  indication,  replies  received  with  no
  3772.           error,  messages  sent with no reply requested.  The counters for
  3773.           replies have two  different  meanings,  depending  on  which  set
  3774.           statistics is concerned.  The servers count the replies sent with
  3775.  
  3776.  
  3777.  
  3778.                                          55
  3779.  
  3780.  
  3781.  
  3782.  
  3783.  
  3784.  
  3785.  
  3786.  
  3787.  
  3788.  
  3789.           and without error indications, and the number  of  requests  that
  3790.           the  server  received  that  did not require a reply at all.  The
  3791.           client library counts the replies received with and without error
  3792.           indications, and the number of requests that the client sent that
  3793.           did not require a reply at all.
  3794.  
  3795.           The following function prints the MESSAGESTATS structure:
  3796.  
  3797.  
  3798.           sm_PrintMessageStats (file, stats)
  3799.           FILE                    *const          file;                   /* IN where to print */
  3800.           MESSAGESTATS    *const          msgStats;               /* IN what to print */
  3801.  
  3802.  
  3803.           The following function tells if a  mounted  volume  is  temporary
  3804.           volume,  a data volume, or a log volume.  See Section 5.1, Manag-
  3805.           ing Volumes, for information about volumes.
  3806.  
  3807.  
  3808.           sm_VolumeProperties (volid, properties)
  3809.           VOLID           volid;                  /* IN which volume is of interest */
  3810.           int                     *properties;            /* OUT the properties */
  3811.  
  3812.  
  3813.           Sm_VolumeProperties( ) returns a set of bits  that  tell  whether
  3814.           the  given  volume  is  a data volume or a temporary volume.  The
  3815.           "volid" argument is the volume identifier of the volume in  ques-
  3816.           tion.   If  the volume is not mounted when Sm_VolumeProperties( )
  3817.           is called,  Sm_VolumeProperties( ) mounts it.
  3818.  
  3819.           VOLPROP_TEMP indicates that the volume is temporary (see  Section
  3820.           5.1.3, Temporary Volumes).  If the bit VOLPROP_TEMP is not set in
  3821.           the result, the volume is a data volume.  A log volume cannot  be
  3822.           mounted by a client, and an attempt to get a log volume's proper-
  3823.           ties results in an error.
  3824.  
  3825.  
  3826.           sm_AddServerVolume (flags, volid, option, value)
  3827.           FLAGS           flags;                  /* IN which servers are of interest */
  3828.           VOLID           volid;                  /* IN which volume is of interest */
  3829.           char            *option;                        /* IN which format option to use */
  3830.           char            *value;                 /* IN value for the format option */
  3831.  
  3832.  
  3833.           Sm_AddServerVolume( ) adds a volume  to  the  list  of  mountable
  3834.           volumes on one or more servers (although it seldom makes sense to
  3835.           do this on more than one server with a single pair of arguments).
  3836.           The  "flags"  argument  indicates  which servers are of interest.
  3837.           The "volid" argument is the volume identifier of the volume  that
  3838.           will   determine   which   server  to  contact  when  "flags"  ==
  3839.           VOL_BY_VOLID.  The "option" is one of the server's format options
  3840.           ("dataformat"  or  "tempformat").   The  "value"  argument is the
  3841.  
  3842.  
  3843.  
  3844.                                          56
  3845.  
  3846.  
  3847.  
  3848.  
  3849.  
  3850.  
  3851.  
  3852.  
  3853.  
  3854.  
  3855.           value to be given the option named in "option".
  3856.  
  3857.           Sm_AddServerVolume( ) adds the named volume to the server's  list
  3858.           of known volumes, but the server does not try to mount the volume
  3859.           or   verify   that   the   volume    exists    or    is    valid.
  3860.           Sm_AddServerVolume( )  fails  if  the  value given conflicts with
  3861.           another volume already in the server's table, either in the  path
  3862.           name  or  the  volume identifier.  If your objective is to change
  3863.           the format information for a path name that is  in  the  server's
  3864.           table,  first  remove  the  existing  format  information  (using
  3865.           sm_RemoveServerVolume( ), described below), and subsequently  add
  3866.           the new information.
  3867.  
  3868.  
  3869.           sm_RemoveServerVolume (flags, volid, volid2remove)
  3870.           FLAGS           flags;                  /* IN which servers are of interest */
  3871.           VOLID           volid;                  /* IN which volume id of server of interest */
  3872.           VOLID           volid2remove;   /* IN which volume to remove */
  3873.  
  3874.  
  3875.           Sm_RemoveServerVolume( ) removes "volid2remove" from one or  more
  3876.           servers'  lists  of  mountable  volumes.   The  volume  cannot be
  3877.           removed from a server's table while the volume is in use. it must
  3878.           be dismounted before it is removed.
  3879.  
  3880.           See also Section 5.1, Managing Volumes.
  3881.  
  3882.           4.11.3.  Tuning the Application
  3883.  
  3884.           The size of the application's  buffer  pool,  determined  by  the
  3885.           "bufpages"  option, is the primary tuning parameter that is under
  3886.           the control of applications. The "bufpages" option indicates  the
  3887.           number of MIN_PAGESIZE pages in the buffer pool. It should be set
  3888.           large enough to hold the application's working  set  of  objects.
  3889.           The  buffer  pool  must  not  exceed  the size of physical memory
  3890.           available to the client.
  3891.  
  3892.  
  3893.  
  3894.  
  3895.  
  3896.  
  3897.  
  3898.  
  3899.  
  3900.  
  3901.  
  3902.  
  3903.  
  3904.  
  3905.  
  3906.  
  3907.  
  3908.  
  3909.  
  3910.                                          57
  3911.  
  3912.  
  3913.  
  3914.  
  3915.  
  3916.  
  3917.  
  3918.  
  3919.  
  3920.  
  3921.           5.  USING STORAGE MANAGER SERVERS
  3922.  
  3923.           Storage Manager servers provide  disk,  file,  transaction,  con-
  3924.           currency  control,  and  recovery  services  to clients.  In most
  3925.           respects, users do not have to understand how servers  work,  but
  3926.           there  are a few things that administrators should know; we focus
  3927.           on those things in this section. The first half of  this  section
  3928.           explains  how  to manage volumes. The second half explains how to
  3929.           operate a server.
  3930.  
  3931.  
  3932.           5.1.  Managing Volumes
  3933.  
  3934.           Servers store data on volumes, which can be  Unix  files  or  raw
  3935.           disk  partitions. Each server is composed of a server process and
  3936.           one disk process for each mounted volume. When a server  requires
  3937.           I/O,  it  asks the appropriate disk process to read from or write
  3938.           to the server's buffer pool, which is located in a Unix System  V
  3939.           shared-memory segment. The disk processes perform I/O so that the
  3940.           server never blocks when I/O is required.  The  server  mounts  a
  3941.           volume  before using it, and the server dismounts the volume when
  3942.           it is no longer in use.  Mounting a volume consists in forking  a
  3943.           disk process for that volume.  Dismounting the volume consists in
  3944.           flushing all dirty pages to the disk  and  killing  the  volume's
  3945.           disk process.
  3946.  
  3947.           Volumes are created with the formatvol program, which establishes
  3948.           a  volume's  identifier,  size,  type, and other characteristics.
  3949.           Volumes come in three types: log volumes, data volumes, and  tem-
  3950.           porary volumes.
  3951.  
  3952.           5.1.1.  Log Volumes
  3953.  
  3954.           Log volumes are used to store log information for aborting  tran-
  3955.           sactions  and for recovery. The server has one log volume mounted
  3956.           at all times.
  3957.  
  3958.           5.1.2.  Data Volumes
  3959.  
  3960.           Data volumes are used to store objects and indexes that are meant
  3961.           to  exist  after a transaction ends.  Changes to data volumes are
  3962.           logged so that transactions can  be  aborted  or  committed  with
  3963.           reliability, and so that recovery can be performed after a crash.
  3964.  
  3965.           5.1.3.  Temporary Volumes
  3966.  
  3967.           Some applications store temporary private data and  do  not  need
  3968.           concurrency  control  or  recovery.  The Storage Manager provides
  3969.           temporary volumes for this purpose. Locks are  not  acquired  for
  3970.           data  in  temporary volumes, and updates to temporary volumes are
  3971.           not logged. Temporary volumes are less costly to  use  than  data
  3972.           volumes  are,  but  the  data  on  them  cannot  be  shared among
  3973.  
  3974.  
  3975.  
  3976.                                          58
  3977.  
  3978.  
  3979.  
  3980.  
  3981.  
  3982.  
  3983.  
  3984.  
  3985.  
  3986.  
  3987.           transactions.  The data on temporary volumes are deleted  at  the
  3988.           conclusion  of  the  transaction that creates them, regardless of
  3989.           whether the  transaction  is  committed  or  aborted.   Temporary
  3990.           volumes cannot contain root entries.
  3991.  
  3992.           The server can serve many  data  volumes  and  temporary  volumes
  3993.           simultaneously.
  3994.  
  3995.           5.1.4.  Raw Partitions and Unix Files
  3996.  
  3997.           A volume can be a Unix file or a Unix raw partition.  When a  raw
  3998.           partition  is  used,  data  are  transferred between the server's
  3999.           buffer pool and the disk by the disk process, bypassing the  Unix
  4000.           file system's buffer pool.
  4001.  
  4002.           When a Unix file is used, the data are written to the  Unix  file
  4003.           system's  buffer  pool,  and  the  operating system worries about
  4004.           flushing the data to the disk.  In this case, the  server  forces
  4005.           the  data  to  the  disk periodically with a Unix fsync( ) system
  4006.           call.
  4007.  
  4008.           5.1.5.  Formatting Volumes
  4009.  
  4010.           Before a volume can be used, it must be formatted. This  is  done
  4011.           using  the  formatvol program, which can also display information
  4012.           about previously formatted volumes.  Formatvol  uses  the  confi-
  4013.           guration  options  "dataformat", "tempformat", and "logformat" to
  4014.           determine what characteristics to give volumes that  it  formats.
  4015.           The options have values that list the following information:
  4016.  
  4017.           path      The Unix path name of the volume, e.g., /dev/rz2c.
  4018.  
  4019.           volid     The volume identifier  for  this  volume,  an  integer,
  4020.                     e.g., 8000.
  4021.  
  4022.           #cyl      The number of cylinders on this disk, e.g., 1224 for  a
  4023.                     DEC RZ55.  May be 1.
  4024.  
  4025.           #trk/cyl  The number of tracks per cylinder e.g., 15  for  a  DEC
  4026.                     RZ55.  May be 1.
  4027.  
  4028.           #sect/trk The number of sectors or blocks per track e.g., 36  for
  4029.                     a  DEC  RZ55.  May be the number of blocks in the file.
  4030.                     A block is MIN_PAGESIZE bytes; MIN_PAGESIZE is  defined
  4031.                     in  sm_client.h.   (This  is  determined by the Storage
  4032.                     Manager, not by the device.)  [4]
  4033.  
  4034.           #KB/pg    For logformat only.  This gives the page size  for  log
  4035.                     pages,  in kilobytes.  The value given here may be 4 or
  4036.                     larger, and must be a power of 2.
  4037.  
  4038.           Formatvol collects the format information from the options in the
  4039.           configuration  files,  after which it determines which volumes to
  4040.           format or to display  by  processing  the  options  "volume"  and
  4041.           "display"  from  the  command  line.   The options that formatvol
  4042.           understands are summarized in Table 2.
  4043.  
  4044.  
  4045.  
  4046.  
  4047.  
  4048.  
  4049.  
  4050.  
  4051.  
  4052.  
  4053.  
  4054.           _________________________________________________________________________________
  4055.              Option             Option                            Option
  4056.               Name               Type                           Description
  4057.           _________________________________________________________________________________
  4058.            tempformat   string,int,int,int       path,volid,#cyl,#trk/cyl,#sect/trk
  4059.            dataformat   string,int,int,int       path,volid,#cyl,#trk/cyl,#sect/trk
  4060.            logformat    string,int,int,int,int   path,volid,#cyl,#trk/cyl,#sect/trk,#KB/pg
  4061.            volume       int                      volume to format - command line only
  4062.            display      int                      volume to display - command line only
  4063.           _________________________________________________________________________________
  4064.           |
  4065.  
  4066.  
  4067.  
  4068.  
  4069.  
  4070.  
  4071.  
  4072.                       |
  4073.  
  4074.  
  4075.  
  4076.  
  4077.  
  4078.  
  4079.  
  4080.                                                |
  4081.  
  4082.  
  4083.  
  4084.  
  4085.  
  4086.  
  4087.  
  4088.                                                                                            |
  4089.  
  4090.  
  4091.  
  4092.  
  4093.  
  4094.  
  4095.  
  4096.  
  4097.  
  4098.                               Table 2: Formatvol Options.
  4099.               Fields are separated by white space, commas, colons or semicolons.
  4100.  
  4101.  
  4102.           For example, to print information about the volumes  with  volids
  4103.           8000 and 4000 use:
  4104.  
  4105.               formatvol -dis 8000 -dis 4000
  4106.  
  4107.  
  4108.           To format a data volume with volid 8000 and  a  temporary  volume
  4109.           with volid 4000 use:
  4110.  
  4111.               formatvol -vol 8000 -vol 4000
  4112.  
  4113.  
  4114.           Formatting a volume writes a volume header  and  initializes  the
  4115.           bitmaps  that  describe  the free blocks on the volume.  A volume
  4116.           that is reformatted after being used loses all its data.
  4117.  
  4118.           The Storage Manager does not prevent a volume from being  format-
  4119.           ted while it is in use by a server, even though it will cause the
  4120.           server to crash unrecoverably. Be certain that a  volume  is  not
  4121.           mounted before you format it! [5] A volume is unmounted when  all
  4122.           clients  that are using the volume have completed transactions on
  4123.           it and have unmounted it.  (A client may unmount a volume  expli-
  4124.           citly   with  sm_DismountVolume( ),  or  by  shutting  down  with
  4125.           sm_ShutDown( ) or exit( ).)
  4126.  
  4127.           During recovery, a server mounts the volumes that need  recovery.
  4128.           The  volumes  are  dismounted  when  recovery is completed.  If a
  4129.           volume was in use at the time its server crashed, do not reformat
  4130.           the  volume  until a new server recovers the data on that volume.
  4131.           If you do, the server's log will be inconsistent with the data on
  4132.           ____________________
  4133.              [4] The format of a volume does not  affect  performance  with
  4134.           most  modern  disks.  The easiest way to format volumes it to use
  4135.           use 1 cyl, 1 track/cyl, and let the sect/trk account for the size
  4136.           of the entire volume.
  4137.           ____________________
  4138.  
  4139.  
  4140.  
  4141.                                          60
  4142.  
  4143.  
  4144.  
  4145.  
  4146.  
  4147.  
  4148.  
  4149.  
  4150.  
  4151.  
  4152.           the volume, and the server will crash  during  recovery,  and  it
  4153.           will  be  unable to recover from that.  You can reformat the data
  4154.           volumes and the log volume to get a server running again, but you
  4155.           will have lost all data on the volumes.
  4156.  
  4157.           The log volume is mounted whenever the server is  running,  so  a
  4158.           log volume can be formatted ONLY when the server is not running.
  4159.  
  4160.           5.1.6.  Size Requirements for Log Volumes
  4161.  
  4162.           How large should a log volume be?   The  answer  depends  on  the
  4163.           expected  transaction  mix.  More specifically, it depends on the
  4164.           age of the oldest (longest running) transaction in the system and
  4165.           the amount of log space used by all active transactions. Here are
  4166.           some general rules to determine the  amount  of  free  log  space
  4167.           available in the system.
  4168.  
  4169.            (1)   The physical log is circular.  Log space between the first
  4170.                  log  record generated by the oldest active transaction and
  4171.                  the most recent log record generated  by  any  transaction
  4172.                  cannot be reused.
  4173.  
  4174.            (2)   Log space for a transaction is available  for  reuse  when
  4175.                  the  transaction  has  committed  or  completely  aborted.
  4176.                  Aborting a transaction causes log space  to  be  used,  so
  4177.                  space  is  reserved for aborting each transaction.  Enough
  4178.                  log space must be available to commit or abort all  active
  4179.                  transactions at all times.
  4180.  
  4181.            (3)   Only space starting at the beginning of  the  log  can  be
  4182.                  reused.   This  space  can  be  reused  if it contains log
  4183.                  records only for transactions meeting rule 2.
  4184.  
  4185.            (4)   All sm_WriteObject( ) calls require log  space  twice  the
  4186.                  size  of  the  space written in the object. All calls that
  4187.                  create, grow, or shrink objects require log space equal to
  4188.                  the  size created, inserted, or deleted.  Log records gen-
  4189.                  erated by these calls (generally one  per  call)  have  an
  4190.                  overhead of approximately 50 bytes.
  4191.  
  4192.            (5)   File operations are logged, but the space requirements for
  4193.                  them  are most often negligible, since they are relatively
  4194.                  rare operations, and are often performed in short transac-
  4195.                  tions.
  4196.  
  4197.  
  4198.           ____________________
  4199.                 [5] The Storage Manager ought to lock volumes with  Unix  file
  4200.           locks,  but  Unix  does  not  provide  an  adequate mechanism for
  4201.           locking and unlocking files in the context of crash recovery.
  4202.  
  4203.  
  4204.  
  4205.  
  4206.  
  4207.                                          61
  4208.  
  4209.  
  4210.  
  4211.  
  4212.  
  4213.  
  4214.  
  4215.  
  4216.  
  4217.  
  4218.            (6)   The amount of log space reserved for aborting  a  transac-
  4219.                  tion  is equal to the amount of log space generated by the
  4220.                  transaction (for the purpose of  committing  the  transac-
  4221.                  tion).
  4222.  
  4223.            (7)   When insufficient log space is available  for  a  transac-
  4224.                  tion, the transaction is aborted.
  4225.  
  4226.            (8)   The log should be at least 1 Mbyte (250 pages).
  4227.  
  4228.           For example, consider a transaction T1, which creates 300 objects
  4229.           of  size 2,000 bytes, writes 20 bytes in 100 objects, and is com-
  4230.           mitted. T1 requires at 615 Kbytes for the creates and 9 Kbytes of
  4231.           log  space  for  the  writes. Since log space must be reserved to
  4232.           abort the transaction, the log size must be over 1.248 Mbytes  to
  4233.           run this transaction. Assuming T1 is the only transaction running
  4234.           in the system, all the log space it  uses  and  reserves  becomes
  4235.           available  when  it  completes.   If  another transaction, T2, is
  4236.           started at the same time as T1, but is still running after T1  is
  4237.           committed,  only the reserved space for T1 is available for other
  4238.           transactions.  The portion of the log used by T1 and  T2  is  not
  4239.           available until T2 is finished.
  4240.  
  4241.           Transactions that fail because of insufficient log space are com-
  4242.           monly  those that load a large number of objects into a file dur-
  4243.           ing the creation of a database. A solution to this problem is  to
  4244.           load  the file in a series of smaller transactions. When the last
  4245.           transaction is committed, the load is complete. If the load needs
  4246.           to be aborted, a separate transaction is run to destroy the file.
  4247.  
  4248.           5.1.7.  Backing Up Volumes
  4249.  
  4250.           The Storage Manager does not support media recovery,  so  backing
  4251.           up  critical data volumes is wise. A volume may be backed up when
  4252.           it is unmounted and needs no recovery.  If a volume is stored  on
  4253.           a  Unix  file, a simple copy of the file can be used as a backup.
  4254.           For volumes stored on a raw disk partition, the Unix  dd(1)  com-
  4255.           mand  can  be  used  to  backup  the volume to a Unix file and to
  4256.           restore it. For example,  to  save  a  copy  of  the  raw  device
  4257.           /dev/rrz4d in the Unix file backup.rrz4d use:
  4258.  
  4259.               dd if=/dev/rrz4d of=backup.rrz4d.
  4260.  
  4261.           To restore the backup, use:
  4262.  
  4263.               dd if=backup.rrz4d of=/dev/rrz4d.
  4264.  
  4265.  
  4266.  
  4267.  
  4268.  
  4269.  
  4270.  
  4271.  
  4272.  
  4273.                                          62
  4274.  
  4275.  
  4276.  
  4277.  
  4278.  
  4279.  
  4280.  
  4281.  
  4282.  
  4283.  
  4284.           5.2.  Using the Server
  4285.  
  4286.           In this section we explain  how  to  operate  a  Storage  Manager
  4287.           server.   For  the  purpose  of  this discussion, we use only one
  4288.           server, although any number of servers can be used to manage  any
  4289.           number  of  volumes.   We begin with starting and configuring the
  4290.           server. Next, we discuss  what  the  server  does  during  normal
  4291.           operation.  We  follow  this  with  instructions for shutting the
  4292.           server down. Finally, we explain how  the  server  recovers  from
  4293.           failure.
  4294.  
  4295.           5.2.1.  Starting the Server
  4296.  
  4297.           The server is composed of two  executable  files:  sm_server  and
  4298.           diskrw.  Sm_server is the main server program.  Diskrw is started
  4299.           by the server, as a separate process for each mounted volume, for
  4300.           performing  asynchronous  disk  I/O.  These processes communicate
  4301.           with the server through sockets, semaphores, and  shared  memory.
  4302.           By  default,  the  server assumes diskrw is located in the user's
  4303.           path. An option, described below, can  be  used  to  change  this
  4304.           assumption.
  4305.  
  4306.           When the server is started, it processes  configuration  options.
  4307.           These  options  are  discussed  further below. Second, the server
  4308.           allocates the buffer pool. The buffer pool is located  in  shared
  4309.           memory,  so the operating system must have shared-memory support.
  4310.           Furthermore, the machine on  which  the  server  runs  must  have
  4311.           enough  shared  memory to accommodate the entire buffer pool.  If
  4312.           not enough shared memory is available, the server prints  a  mes-
  4313.           sage,  indicating how much shared memory it is trying to acquire,
  4314.           and exits.
  4315.  
  4316.           Third, the server mounts the log volume. If  the  log  volume  is
  4317.           newly  formatted,  it is regenerated. When a log volume is regen-
  4318.           erated, the entire log is cleared and written to disk. This  will
  4319.           take  noticeable  time  if the volume is large. If the log is not
  4320.           regenerated, recovery analysis is performed.
  4321.  
  4322.           If no volumes require recovery, all phases of  recovery  complete
  4323.           in  less  than  one  second.  If the analysis determines that any
  4324.           volumes require recovery (due to a previous failure of some sort:
  4325.           operating  system  failure,  machine  failure, internal error, or
  4326.           because a user killed the server), recovery  is  performed.  Data
  4327.           volumes  that  were  mounted  at  the  time  of  the  failure are
  4328.           remounted, updates by committed transactions  are  restored,  and
  4329.           all  transactions in progress at the time of failure are aborted.
  4330.           When recovery is complete, the data volumes are dismounted and  a
  4331.           checkpoint is taken.
  4332.  
  4333.           The server now begin to process requests from clients.
  4334.  
  4335.  
  4336.  
  4337.  
  4338.  
  4339.                                          63
  4340.  
  4341.  
  4342.  
  4343.  
  4344.  
  4345.  
  4346.  
  4347.  
  4348.  
  4349.  
  4350.           5.2.2.  Configuring the Server
  4351.  
  4352.           There are several configuration options that can be set when  the
  4353.           server is started. A brief description of the options is given in
  4354.           Table 3. Most options have default values, but some do  not,  and
  4355.           these  must  be  given values, either on the command line or in a
  4356.           configuration file.  See Section 3 for general  information  that
  4357.           applies to all options.
  4358.  
  4359.           Option values are read from the the default  configuration  files
  4360.           /usr/lib/sm_config,  $HOME/.sm_config,  and  ./.sm_config in that
  4361.           order, if they exist. If the command-line option "skipdefault" is
  4362.           given, these default files are not read.
  4363.  
  4364.           Options on the command line are read after the default files  are
  4365.           read.  Command-line options are prefixed by a "-". In addition to
  4366.           options, a server accepts the command-line flags given  in  Table
  4367.           4. Command-line flags are prefixed by a "-".
  4368.  
  4369.           When given the "help" flag, a server prints a list of the  avail-
  4370.           able options and flags, and exits.
  4371.  
  4372.           The "skipdefault" flag prevents a server from reading the default
  4373.           configuration files. It must be the first argument on the command
  4374.           line if it is used.
  4375.  
  4376.           The "force" flag prevents a server from checking  with  the  user
  4377.           before regenerating the log.
  4378.  
  4379.           The "background"  flag causes the server to disconnect  from  its
  4380.           controlling  terminal.   This flag is available for users who run
  4381.           the server from shells that, like the Bourne shell, do  not  have
  4382.           real job control.
  4383.  
  4384.           We now describe each option from Table 2.
  4385.  
  4386.           The "config" option specifies a configuration file to read  after
  4387.           default  configuration  files  have  been  read.   This option is
  4388.           effective only on the command line.
  4389.  
  4390.           The "verbose" option is used to turn on and off printing  of  the
  4391.           option  values at startup. Options are printed to the file speci-
  4392.           fied by "errorfile" option (q.v.).
  4393.  
  4394.           The "bufpages" option indicates the number of MIN_PAGESIZE  pages
  4395.           to  be  used for a server's buffer pool. The option must be given
  4396.           for a server to run.  This option  determines  the  size  of  the
  4397.           shared memory segment allocated by the server.  The shared memory
  4398.           segment will be MIN_PAGESIZE*bufpages bytes long plus  a  few  KB
  4399.           extra.   Section  5.3,  Tuning  the  Server, for more information
  4400.           about setting this option.
  4401.  
  4402.  
  4403.  
  4404.  
  4405.                                          64
  4406.  
  4407.  
  4408.  
  4409.  
  4410.  
  4411.  
  4412.  
  4413.  
  4414.  
  4415.  
  4416.  
  4417.  
  4418.           _______________________________________________________________________________________________________
  4419.               Option       Option        Possible               Default                       Option
  4420.                Name         Type          Values                 Values                    Description
  4421.           _______________________________________________________________________________________________________
  4422.            config          string    file name           /usr/lib/sm_config       read a configuration file
  4423.                                                          $HOME/.sm_config         defaults is read unless
  4424.                                                          ./.sm_config             skipdefault is set
  4425.            verbose         Boolean   yes no              no                       print configuration options
  4426.            bufpages        int       > 32                none                     number of buffer pool pages
  4427.            logvolume       string    path name           none                     name of the log volume
  4428.            portname        string    name or number      exodussm                 port name or port number
  4429.                                                                                   for a server; if a name, it
  4430.                                                                                   must be in /etc/services
  4431.            errorfile       string    file name           - (stderr)               file for errors,
  4432.                                                                                   warnings, progress
  4433.            regenlog        Boolean   yes no              no                       clear the log,
  4434.            shutdown        Boolean   yes no              no                       shut down after recovery
  4435.                                                                                   or regeneration of log
  4436.            checkpoints     int       > 1                 100                      checkpoint frequency
  4437.                                                                                   (based on number of log pages)
  4438.            diskproc        string    file name           /usr/lib/exodus/diskrw   disk I/O program name
  4439.            intercache      Boolean   yes no              yes                      allow caching of pages
  4440.                                                                                   at the client between
  4441.                                                                                   transactions
  4442.            progress        Boolean   yes no              no                       control progress printing
  4443.            maxclients      int       > 0                 20                       maximum number of
  4444.                                                                                   clients to be served
  4445.                                                                                   simultaneously
  4446.            maxthreads      int       > 1                 function(maxclients)     maximum number of
  4447.                                                                                   threads.
  4448.            traceflags      int       hex number          0x0                      set tracing flags.
  4449.                                                                                   Available if server is
  4450.                                                                                   compiled with -DDEBUG.
  4451.            tempformat      string                                                 see Table 2.
  4452.            dataformat      string                                                 see Table 2.
  4453.            logformat       string                                                 see Table 2.
  4454.            maxaddvolumes   int       small number >= 0   0                        increases volume table size
  4455.            wrapcount       int       >=0                 0                        starting wrap count for log
  4456.           _______________________________________________________________________________________________________
  4457.           |
  4458.  
  4459.  
  4460.  
  4461.  
  4462.  
  4463.  
  4464.  
  4465.  
  4466.  
  4467.  
  4468.  
  4469.  
  4470.  
  4471.  
  4472.  
  4473.  
  4474.  
  4475.  
  4476.  
  4477.  
  4478.  
  4479.  
  4480.  
  4481.  
  4482.  
  4483.  
  4484.  
  4485.  
  4486.  
  4487.  
  4488.  
  4489.  
  4490.  
  4491.  
  4492.  
  4493.  
  4494.                          |
  4495.  
  4496.  
  4497.  
  4498.  
  4499.  
  4500.  
  4501.  
  4502.  
  4503.  
  4504.  
  4505.  
  4506.  
  4507.  
  4508.  
  4509.  
  4510.  
  4511.  
  4512.  
  4513.  
  4514.  
  4515.  
  4516.  
  4517.  
  4518.  
  4519.  
  4520.  
  4521.  
  4522.  
  4523.  
  4524.  
  4525.  
  4526.  
  4527.  
  4528.  
  4529.  
  4530.  
  4531.                                    |
  4532.  
  4533.  
  4534.  
  4535.  
  4536.  
  4537.  
  4538.  
  4539.  
  4540.  
  4541.  
  4542.  
  4543.  
  4544.  
  4545.  
  4546.  
  4547.  
  4548.  
  4549.  
  4550.  
  4551.  
  4552.  
  4553.  
  4554.  
  4555.  
  4556.  
  4557.  
  4558.  
  4559.  
  4560.  
  4561.  
  4562.  
  4563.  
  4564.  
  4565.  
  4566.  
  4567.  
  4568.                                                        |
  4569.  
  4570.  
  4571.  
  4572.  
  4573.  
  4574.  
  4575.  
  4576.  
  4577.  
  4578.  
  4579.  
  4580.  
  4581.  
  4582.  
  4583.  
  4584.  
  4585.  
  4586.  
  4587.  
  4588.  
  4589.  
  4590.  
  4591.  
  4592.  
  4593.  
  4594.  
  4595.  
  4596.  
  4597.  
  4598.  
  4599.  
  4600.  
  4601.  
  4602.  
  4603.  
  4604.  
  4605.                                                                                 |
  4606.  
  4607.  
  4608.  
  4609.  
  4610.  
  4611.  
  4612.  
  4613.  
  4614.  
  4615.  
  4616.  
  4617.  
  4618.  
  4619.  
  4620.  
  4621.  
  4622.  
  4623.  
  4624.  
  4625.  
  4626.  
  4627.  
  4628.  
  4629.  
  4630.  
  4631.  
  4632.  
  4633.  
  4634.  
  4635.  
  4636.  
  4637.  
  4638.  
  4639.  
  4640.  
  4641.  
  4642.                                                                                                                  |
  4643.  
  4644.  
  4645.  
  4646.  
  4647.  
  4648.  
  4649.  
  4650.  
  4651.  
  4652.  
  4653.  
  4654.  
  4655.  
  4656.  
  4657.  
  4658.  
  4659.  
  4660.  
  4661.  
  4662.  
  4663.  
  4664.  
  4665.  
  4666.  
  4667.  
  4668.  
  4669.  
  4670.  
  4671.  
  4672.  
  4673.  
  4674.  
  4675.  
  4676.  
  4677.  
  4678.  
  4679.  
  4680.  
  4681.  
  4682.                               Table 3: Server Options
  4683.  
  4684.  
  4685.  
  4686.  
  4687.  
  4688.  
  4689.  
  4690.  
  4691.  
  4692.  
  4693.  
  4694.                                          65
  4695.  
  4696.  
  4697.  
  4698.  
  4699.  
  4700.  
  4701.  
  4702.  
  4703.  
  4704.  
  4705.            ______________________________________________________________
  4706.                Flag                            Flag
  4707.                Name                           Effect
  4708.            ______________________________________________________________
  4709.             help          print a message and exit
  4710.             skipdefault   do not read default configuration files
  4711.                           must be the first argument on the command line
  4712.             force         do not confirm log regeneration option
  4713.             background    put in background (for use with Bourne shell)
  4714.            ______________________________________________________________
  4715.            |
  4716.  
  4717.  
  4718.  
  4719.  
  4720.  
  4721.  
  4722.  
  4723.                         |
  4724.  
  4725.  
  4726.  
  4727.  
  4728.  
  4729.  
  4730.  
  4731.                                                                          |
  4732.  
  4733.  
  4734.  
  4735.  
  4736.  
  4737.  
  4738.  
  4739.  
  4740.  
  4741.  
  4742.                         Table 4: Server Command-Line Flags
  4743.  
  4744.           The "logvolume" option gives the path name  of  the  volume  that
  4745.           contains the log. A value must be given for the log volume.
  4746.  
  4747.           The "portname" option indicates a port  number  or  the  symbolic
  4748.           name  of  a  port entry in /etc/services.  The server connects to
  4749.           this port and listens  for  client  requests  on  it.  To  enable
  4750.           clients  to  locate  a server with a symbolic port name, the port
  4751.           name must to present in /etc/services  on  both  the  client  and
  4752.           server  machines. If no port name is given, a server looks for an
  4753.           entry "exodussm", registered for use with TCP, in /etc/services.
  4754.  
  4755.           By using port numbers instead of symbolic names avoids  the  need
  4756.           for  entries  in /etc/services. See the Unix manual page for ser-
  4757.           vices(5). An example entry for the default server name is:
  4758.  
  4759.               exodussm    1152/tcp            # exodus storage manager
  4760.  
  4761.  
  4762.           The "errorfile" option directs server error messages and diagnos-
  4763.           tics to the given file. A value of "-" means that stderr is used.
  4764.  
  4765.           The "regenlog" option causes the log on  the  log  volume  to  be
  4766.           regenerated. This overwrites all log records, so it should not be
  4767.           done unless the  server  was  last  shut  down  cleanly.   Server
  4768.           automatically  regenerate their logs when they are started with a
  4769.           newly formatted log volumes.  When the option is set to "yes",  a
  4770.           confirmation  is  requested.  The confirmation can be disabled by
  4771.           starting the server with the "force" option.
  4772.  
  4773.           The "shutdown" option causes a server to  shut  down  immediately
  4774.           after performing recovery or regenerating the log.
  4775.  
  4776.           The "checkpoints" option sets  the  checkpoint  frequency  for  a
  4777.           server.  The  value  represents  the  number of log pages written
  4778.           between checkpoints.
  4779.  
  4780.           The "progress" option causes a server to print  messages  tracing
  4781.           its progress. This is used for debugging; it slows the server.
  4782.  
  4783.  
  4784.  
  4785.                                          66
  4786.  
  4787.  
  4788.  
  4789.  
  4790.  
  4791.  
  4792.  
  4793.  
  4794.  
  4795.  
  4796.           The "diskproc" option specifies the path name  of  the  disk  I/O
  4797.           program to be used by the server.
  4798.  
  4799.           The "intercache" option allows experiments to  be  run  with  and
  4800.           without inter-transaction caching of pages on the client.
  4801.  
  4802.           The "maxclients" option determines the number of clients a server
  4803.           can server at any one time.  Servers create internal tables whose
  4804.           size depends on this value.
  4805.  
  4806.           The "maxthreads" value, determined  by  the  "maxclients"  value,
  4807.           should  be sufficient, but can be overridden.  If a server recov-
  4808.           ers from a failure without running out of threads, it has  enough
  4809.           threads to handle client requests.  If numerous distributed tran-
  4810.           sactions are active at the time of a server failure, it is possi-
  4811.           ble,  but  unlikely,  that the server will not be able to recover
  4812.           with the default number of threads.
  4813.  
  4814.           The "traceflags" option is available only with a server that  was
  4815.           compiled  with  debugging  (the  -DDEBUG flag).  It is useful for
  4816.           programmers who are modifying the Storage Manager source code and
  4817.           testing their changes.
  4818.  
  4819.           The "dataformat", "logformat", and "tempformat"  options  are  as
  4820.           described  in  Section  5.1.5,   Formatting Volumes.  Servers can
  4821.           mount and use volumes given in these options.
  4822.  
  4823.           The "maxaddvolumes" option indicates how large  the  mount  table
  4824.           will  be.   The  server reads its configuration files, counts the
  4825.           volumes named in the format options, and creates  a  mount  table
  4826.           large enough to mount this many volumes and "maxaddvolumes" more.
  4827.           This is a strict limit to the number of volumes that  the  server
  4828.           can  mount (at any one time) as long as it is running.  The value
  4829.           of  "maxaddvolumes" should not be  boosted  frivolously,  because
  4830.           the  size  of the mount table affects the amount of shared memory
  4831.           required by the server.  The default value is 0.
  4832.  
  4833.           The "wrapcount" option is rarely needed.  The  server  will  tell
  4834.           you if you ever need to set this option.  It is needed if you add
  4835.           volumes after the server starts (maxaddvolumes > 0), and a volume
  4836.           that  you  are  add was updated by a server running on a log that
  4837.           differs from the current log (or the log  was  regenerated  since
  4838.           the added volume was last mounted.)
  4839.  
  4840.  
  4841.           5.2.3.  Normal Operation of Servers
  4842.  
  4843.           During normal  operation,  servers  listen  for  connections  and
  4844.           requests  from  clients  and  monitor terminal input.  Error mes-
  4845.           sages are printed  on  the  servers  terminals  when  interesting
  4846.           events  occur,  for  example,  when  a deadlock is detected, or a
  4847.           transaction is aborted by a server because of a problem  such  as
  4848.  
  4849.  
  4850.  
  4851.                                          67
  4852.  
  4853.  
  4854.  
  4855.  
  4856.  
  4857.  
  4858.  
  4859.  
  4860.  
  4861.  
  4862.           insufficient log space.
  4863.  
  4864.           5.2.3.1.  Server Commands
  4865.  
  4866.           The following commands can be invoked from the standard input  to
  4867.           the  server:  "help",  "shutdown", "kill", "crash", "checkpoint",
  4868.           "printstats",  "clearstats",  "progress",  "user",   "addvolume",
  4869.           "rmvolume",  "listvolumes",  "listmount",  "listdistr", "source",
  4870.           "redirect".  When  the  server  is  compiled  with  profiling  (-
  4871.           DPROFIL,  -p), the server accepts the "profil" command.  When the
  4872.           server is compiled with  debugging  (-DDEBUG),  the  server  also
  4873.           accepts the "traceflags" and "tracelevel" commands.
  4874.  
  4875.           The "help" command provides a list of the commands.
  4876.  
  4877.           The "shutdown" command instructs the server to abort  all  active
  4878.           transactions  and  cleanly  shut down.  The "kill" command causes
  4879.           the server to halt immediately after  displaying  the  status  of
  4880.           mounted  volumes.  The "crash" command has the same effect as the
  4881.           "kill" command, except that a core dump is produced as well.
  4882.  
  4883.           The "checkpoint" command causes the server to take  a  checkpoint
  4884.           immediately.   Checkpoints are taken periodically by servers. The
  4885.           default frequency is once every 100 log pages, but  this  can  be
  4886.           changed       by       an      application      program      (see
  4887.           sm_ChangeCheckpointFrequency( ) in Section 4.11.2, Administrative
  4888.           Operations).
  4889.  
  4890.           The "printstats" command prints general server  statistics.   The
  4891.           "clearstats" command clears any counters among the statistics.
  4892.  
  4893.           The "progress" command  reverses  the  value  of  the  "progress"
  4894.           option.
  4895.  
  4896.           The "user" command reverses the value of an  internal  flag  that
  4897.           determines whether or not the server prints a message when a user
  4898.           (application) error is encountered.  (There is no option to  con-
  4899.           trol this.)
  4900.  
  4901.           The "addvolume" command adds a volume to the  server's  table  of
  4902.           mountable volumes.  The "addvolume" command takes a format-option
  4903.           name and a format-option value.  For example,  to  add  the  data
  4904.           volume 8000, type
  4905.  
  4906.               addvolume dataformat /path/to/datafile:8000:1:1:300
  4907.  
  4908.           A volume cannot be added if the  given  format  information  con-
  4909.           flicts with other information in the table.
  4910.  
  4911.           The "rmvolume" command removes a volume from the  server's  table
  4912.           of  mountable  volumes.   The  command takes a volume identifier.
  4913.           For example, to remove the data volume 8000, type
  4914.  
  4915.  
  4916.  
  4917.                                          68
  4918.  
  4919.  
  4920.  
  4921.  
  4922.  
  4923.  
  4924.  
  4925.  
  4926.  
  4927.  
  4928.               rmvolume 8000
  4929.  
  4930.           A volume cannot be removed if it is in use.
  4931.  
  4932.           The "listvolumes" command prints the server's table of  mountable
  4933.           volumes.
  4934.  
  4935.           The "listmount" command prints a list of the volumes that are  in
  4936.           some  state  of  use: mounted, being mounted or being dismounted.
  4937.           It also prints the number of free "mount slots", which  indicates
  4938.           how many more volumes could be mounted at any one time, given the
  4939.           server's configuration.  To allow more volumes to be  mounted  at
  4940.           once,  shut  the  server  down, boost the value of the "maxaddvo-
  4941.           lumes" option, and restart the server.
  4942.  
  4943.           The "listdistr" command prints information about prepared distri-
  4944.           buted transactions.  These transactions consume space in the log,
  4945.           and if they are not aborted or committed, eventually  the  server
  4946.           will fail because it will have run out of log space.  See Section
  4947.           4.3, Transactions,  Section  4.11.1,  External  Two-Phase  Commit
  4948.           Functions for information about distributed transactions.
  4949.  
  4950.           The "source" command takes one argument, the path name of a  file
  4951.           from  which  to  read  commands.  The server processes these com-
  4952.           mands, and when it reads the last command in the file, it resumes
  4953.           reading  from  the  terminal.   If the path name is missing or is
  4954.           /dev/tty, reading resumes from the terminal.
  4955.  
  4956.           The  "redirect" command takes two arguments.  The first  argument
  4957.           indicates  which  output  stream is to be redirected: messages to
  4958.           the terminal or error messages.  The second argument is the  path
  4959.           name  of  a file to which the output is written.  When the output
  4960.           is redirected again, the stream is flushed to the given file  and
  4961.           the  file  is  closed.   To  redirect output to the terminal, use
  4962.           /dev/tty or omit the path name.
  4963.  
  4964.           The  "profil" command causes the server  to  dump  its  profiling
  4965.           information  to  disk. This command is available only on a server
  4966.           that was compiled with  profiling  on  (-DPROFIL  -p).   See  the
  4967.           manual page for prof(1).
  4968.  
  4969.           The  "traceflags" command may take an integer argument, which may
  4970.           be  a  hexadecimal number, such as "0xfa3", in which case it sets
  4971.           the server's trace flags word to  that  value.   The  command  is
  4972.           available  only with a server that was compiled with debugging on
  4973.           (-DDEBUG -g).  The meanings of the trace flags are found  in  the
  4974.           server's  source code, in src/include/global_trace.h.  When "tra-
  4975.           ceflags" is used with no argument, it prints  the  value  of  the
  4976.           trace flags word.
  4977.  
  4978.           The  "tracelevel" command is available with  a  server  that  was
  4979.           compiled  with  debugging  on  (-DDEBUG  -g).   When used with no
  4980.  
  4981.  
  4982.  
  4983.                                          69
  4984.  
  4985.  
  4986.  
  4987.  
  4988.  
  4989.  
  4990.  
  4991.  
  4992.  
  4993.  
  4994.           argument, it prints the trace level for the trace flags that  are
  4995.           on.   When  given  an  integer argument (1, 2, or 3), it sets the
  4996.           trace level for the trace flags that are on.
  4997.  
  4998.           5.2.4.  Shutting Down the Server
  4999.  
  5000.           The server can be shut down several ways.  One method is  to  use
  5001.           one  of  the  above-mentioned  commands.  Another  is  to run the
  5002.           "shutserver" program, described below, at the end  of  this  sec-
  5003.           tion.    A   third   way  to  shut  down  a  server  is  to  call
  5004.           sm_ShutdownServer( ) in a client program.
  5005.  
  5006.           A server may also shut itself down because of a fatal error, such
  5007.           as  the  unexpected  death  of  a disk process or a bug.  A fatal
  5008.           error causes the server to report the state of  all  the  mounted
  5009.           volumes, dump core, and exit.
  5010.  
  5011.           The server allocates a Unix System V shared-memory segment and  a
  5012.           semaphore  set when it starts. If a server is shut down in a con-
  5013.           trolled fashion, it removes the segment and semaphore set.  These
  5014.           resources  are  not removed when the server is terminated by kill
  5015.           -9 <server process> typed in the shell, by the "kill" or  "crash"
  5016.           command  given  to  the  server's  terminal  monitor, or when the
  5017.           server process is killed by a debugger.  If you use  any  one  of
  5018.           these  means  to  terminate  a  server,  you must use ipcrm(1) to
  5019.           remove the resources.  See  the  manual  pages  for  ipcs(1)  and
  5020.           ipcrm(1)  for  more  information.   If the segments and semaphore
  5021.           sets are not removed, eventually the operating  system  will  run
  5022.           out of segments, and you will be unable to start a new server.
  5023.  
  5024.           If a server shuts down without having committed  or  aborted  all
  5025.           its  active transactions and flushed all its dirty pages to disk,
  5026.           recovery is required when the server is restarted. When a  server
  5027.           shuts  down, it prints the status of all the mounted volumes.  It
  5028.           indicates if recovery is necessary on those volumes.
  5029.  
  5030.           5.2.4.1.  Running the Shutserver program
  5031.  
  5032.           The shutserver program is invoked:
  5033.  
  5034.               shutserver [-m machine] [-s servername] [-h].
  5035.  
  5036.           The "machine" specifies the name of the machine on which runs the
  5037.           server to be shut down. If "-m machine" is not given, the program
  5038.           uses the machine on which shutserver is executed.   The  "server-
  5039.           name"  is the name of the server in /etc/services, If "-s server-
  5040.           name" is not given, "exodussm" is used.  The "-h" option prints a
  5041.           brief help message.
  5042.  
  5043.  
  5044.  
  5045.  
  5046.  
  5047.  
  5048.  
  5049.                                          70
  5050.  
  5051.  
  5052.  
  5053.  
  5054.  
  5055.  
  5056.  
  5057.  
  5058.  
  5059.  
  5060.           5.2.5.  Recovery
  5061.  
  5062.           When a server is started after a failure  it  automatically  per-
  5063.           forms recovery. The time it takes for recovery depends on several
  5064.           factors, including the number of transactions in progress at  the
  5065.           time of the failure, the number of log records generated by these
  5066.           transactions, and the number of log records generated  since  the
  5067.           last checkpoint.
  5068.  
  5069.           Recovery has three phases. After each phase,  the  server  prints
  5070.           information about the time and I/O operations required to perform
  5071.           the phase.
  5072.  
  5073.           The first phase is analysis. The log is scanned to determine what
  5074.           transactions  were  active  and which volumes were mounted at the
  5075.           time of the failure.
  5076.  
  5077.           After analysis, the volumes are mounted and  the  redo  phase  is
  5078.           performed. In the redo phase, data are restored to their state at
  5079.           the time of the failure.
  5080.  
  5081.           In the last phase, the undo phase, the server aborts the transac-
  5082.           tions that were active at the time of the crash.  The volumes are
  5083.           dismounted, and a checkpoint is taken.
  5084.  
  5085.           For details of recovery in the Storage Manager, see [Fran92].
  5086.  
  5087.           5.3.  Tuning the Server
  5088.  
  5089.           There are  several  tuning  parameters  in  the  Storage  Manager
  5090.           server.  The following sections describe each one.
  5091.  
  5092.           5.3.1.1.  The Size of the Buffer Pool
  5093.  
  5094.           The size of a server's buffer pool is  determined  by  the  "buf-
  5095.           pages"  option,  which indicates the number of MIN_PAGESIZE pages
  5096.           in the buffer pool.  If a server is  the  primary  process  on  a
  5097.           machine, it should have a buffer pool close to the size of avail-
  5098.           able shared memory.  When both an application and  a  server  are
  5099.           running  on the same machine, choosing a buffer pool size is more
  5100.           difficult.  A "proper" choice depends  on  the  behavior  of  the
  5101.           applications and their interactions with servers.  A good rule of
  5102.           thumb is that that clients should have the adequate buffer space,
  5103.           to minimize client-server interaction.
  5104.  
  5105.           The buffer pool must fit in the available shared  memory  of  the
  5106.           machine  on  which the server runs.  The server will let you know
  5107.           if it cannot acquire enough shared memory when  it  starts.   See
  5108.           the  manual   pages for ipcs(1) and ipcrm(1) to find out how much
  5109.           shared memory is in use.  See your system administrator  to  find
  5110.           out  how  much shared memory has been configured for your systems
  5111.           if you find that you cannot run a server with a  buffer  pool  of
  5112.  
  5113.  
  5114.  
  5115.                                          71
  5116.  
  5117.  
  5118.  
  5119.  
  5120.  
  5121.  
  5122.  
  5123.  
  5124.  
  5125.  
  5126.           adequate size, and no shared memory segments are being wasted.
  5127.  
  5128.           5.3.1.2.  The Size of Log Pages
  5129.  
  5130.           The log page size is determined when a log volume  is  formatted.
  5131.           For  a  transaction  mix  dominated by transactions that generate
  5132.           more than a few kilobytes of log information, the larger the  log
  5133.           page  size,  the  better. For short running transactions, such as
  5134.           those found in transaction processing  benchmarks,  8  Kbyte  log
  5135.           pages give good results.
  5136.  
  5137.           5.3.1.3.  Checkpoint Frequency
  5138.  
  5139.           The checkpoint frequency is based on  the  number  of  log  pages
  5140.           written.  The default frequency is every 100 log pages.  The fre-
  5141.           quency can be determined by setting the  "checkpoint"  configura-
  5142.           tion  option.  It can be changed in a running server by an appli-
  5143.           cation that calls sm_ChangeCheckpointFrequency( ).  More frequent
  5144.           checkpoints  tend to shorten the time required to recover after a
  5145.           server fails at the expense  of  processing  time  during  normal
  5146.           operation.  Checkpoints also cause the server's dirty pages to be
  5147.           flushed to disk, which may also improve performance during normal
  5148.           operation.
  5149.  
  5150.  
  5151.  
  5152.  
  5153.  
  5154.  
  5155.  
  5156.  
  5157.  
  5158.  
  5159.  
  5160.  
  5161.  
  5162.  
  5163.  
  5164.  
  5165.  
  5166.  
  5167.  
  5168.  
  5169.  
  5170.  
  5171.  
  5172.  
  5173.  
  5174.  
  5175.  
  5176.  
  5177.  
  5178.  
  5179.  
  5180.  
  5181.                                          72
  5182.  
  5183.  
  5184.  
  5185.  
  5186.  
  5187.  
  5188.  
  5189.  
  5190.  
  5191.  
  5192.           6.  REFERENCES
  5193.  
  5194.  
  5195.           [Care86]  M. Carey, D. DeWitt, J.  Richardson,  and  E.  Shekita,
  5196.                     Object  and  File  Management  in the EXODUS Extensible
  5197.                     Database System, Proc. of the 1986 VLDB  Conf.,  Kyoto,
  5198.                     Japan, Aug. 1986.
  5199.  
  5200.           [Care89]  M. Carey, D. DeWitt, E. Shekita, Storage Management for
  5201.                     Objects in EXODUS, Object-Oriented Concepts, Databases,
  5202.                     and  Applications,  W.  Kim  and  F.  Lochovsky,  eds.,
  5203.                     Addison-Wesley, 1989.
  5204.  
  5205.           [Chou85]  H. Chou and D. Dewitt, An Evaluation of Buffer  Manage-
  5206.                     ment  Strategies for Relational Database Systems, Proc.
  5207.                     of the 1985 VLDB Conf., Stockholm, Sweden, Aug. 1985.
  5208.  
  5209.           [Fran92]  M. Franklin, M. Zwilling, C.K.Tan,  M.  Carey,  and  D.
  5210.                     DeWitt,  Crash  Recovery in Client-Server EXODUS, Proc.
  5211.                     of the ACM SIGMOD Int'l. Conf. on Management  of  Data,
  5212.                     San Diego, CA, June 1992.
  5213.  
  5214.           [Gray78]  J. N. Gray, Notes on Database Operating  Systems,  Lec-
  5215.                     ture  Notes  in Computer Science 60, Advanced course on
  5216.                     Operating Systems, ed. G. Seegmuller, Springer  Verlag,
  5217.                     New York 1978.
  5218.  
  5219.           [Gray88]  J. Gray, R. Lorie, G. Putzolu, I. Traiger,  Granularity
  5220.                     of  Locks  and  Degrees of Consistency in a Shared Data
  5221.                     Base, Readings in Database Systems, ed. M. Stonebraker,
  5222.                     Morgan Kaufmann, San Mateo, Ca., 1988.
  5223.  
  5224.           [Litw88]  W. Litwin, Linear Hashing: A  New  Tool  for  File  and
  5225.                     Table  Addressing, Readings in Database Systems, ed. M.
  5226.                     Stonebraker, Morgan Kaufmann, San Mateo, Ca., 1988.
  5227.  
  5228.           [Moha83]  C. Mohan, B. Lindsay, Efficient  Commit  Protocols  for
  5229.                     the  Tree  of  Processes  Model of Distributed Transac-
  5230.                     tions, Proc. 2nd ACM SIGACT/SIGOPS Symposium on Princi-
  5231.                     ples   of   Distributed  Computing,  Montreal,  Canada,
  5232.                     August, 1983.
  5233.  
  5234.           [Moha89]  C. Mohan, D. Haderle, B. Lindsay, H. Pirahesh,  and  P.
  5235.                     Schwarz,  ARIES: A Transaction Recovery Method Support-
  5236.                     ing  Fine-Granularity  Locking  and  Partial  Rollbacks
  5237.                     Using Write-Ahead Logging, ACM Transactions on Database
  5238.                     Systems, Vol. 17, No 1, March 1992.
  5239.  
  5240.           [Rich87]  J. Richardson and M. Carey, Programming Constructs  for
  5241.                     Database  System Implementation in EXODUS, Proc. of the
  5242.                     ACM SIGMOD Int'l. Conf.  on  Management  of  Data,  San
  5243.                     Francisco, CA, May 1987.
  5244.  
  5245.  
  5246.  
  5247.                                          73
  5248.  
  5249.  
  5250.  
  5251.  
  5252.  
  5253.  
  5254.  
  5255.  
  5256.  
  5257.  
  5258.           [exoArch] EXODUS Storage Manager  Architecture  Overview,  unpub-
  5259.                     lished,  included  in  EXODUS  Storage Manager software
  5260.                     release.
  5261.  
  5262.  
  5263.  
  5264.  
  5265.  
  5266.  
  5267.  
  5268.  
  5269.  
  5270.  
  5271.  
  5272.  
  5273.  
  5274.  
  5275.  
  5276.  
  5277.  
  5278.  
  5279.  
  5280.  
  5281.  
  5282.  
  5283.  
  5284.  
  5285.  
  5286.  
  5287.  
  5288.  
  5289.  
  5290.  
  5291.  
  5292.  
  5293.  
  5294.  
  5295.  
  5296.  
  5297.  
  5298.  
  5299.  
  5300.  
  5301.  
  5302.  
  5303.  
  5304.  
  5305.  
  5306.  
  5307.  
  5308.  
  5309.  
  5310.  
  5311.  
  5312.  
  5313.                                          74
  5314.  
  5315.  
  5316.  
  5317.  
  5318.  
  5319.  
  5320.  
  5321.  
  5322.  
  5323.  
  5324.           A.  APPENDIX : Locking Protocol for Storage Manager Operations
  5325.  
  5326.           The Storage Manager performs concurrency control using the  stan-
  5327.           dard  hierarchical  two-phase  locking  protocol  (see  [Gray78],
  5328.           [Gray88]) for locking files and object pages. The lock  hierarchy
  5329.           contains  two  granularities: file-level, and page-level. Locking
  5330.           for index operations is performed with a non-two-phase  protocol,
  5331.           that  allows  multiple clients to read and update the same index.
  5332.           This section describes the lock modes used in the  system,  lists
  5333.           the  locks  requested  for  each  Storage Manager file and object
  5334.           operation, and explains how deadlocks are handled. Lock  acquisi-
  5335.           tion  and  release  are  implicit  in all relevant operations, so
  5336.           clients cannot explicitly manage their own locks.
  5337.  
  5338.           A.1.  Lock Modes
  5339.  
  5340.           Files are locked in one of six modes: no lock (NL),  shared  (S),
  5341.           exclusive  (X),  intent  to share (IS), intent to exclusive (IX),
  5342.           share with intent to exclusive (SIX)  [Gray78],  [Gray88].   Only
  5343.           shared  and  exclusive  locks are obtained on pages.  Determining
  5344.           whether two locks are compatible (eg., when a client holds a lock
  5345.           on  a  file  and  another  client wants to obtain a lock on it as
  5346.           well) can be done using a table. Table A.1 is a lock  compatibil-
  5347.           ity table for the six file lock modes.  Each row indicates a lock
  5348.           that some client can hold,  and  each  column  indicates  a  lock
  5349.           desired  by  another  client.  The Y and N table entries indicate
  5350.           (yes or no) whether the locks are compatible or not.
  5351.  
  5352.  
  5353.  
  5354.                          ___________________________________
  5355.  
  5356.                           Lock         Lock Requested
  5357.                           Held   NL   IS   IX   S   SIX   X
  5358.                          ___________________________________
  5359.                           NL     Y    Y    Y    Y   Y     Y
  5360.  
  5361.                           IS     Y    Y    Y    Y   Y     N
  5362.  
  5363.                           IX     Y    Y    Y    N   N     N
  5364.  
  5365.                           S      Y    Y    N    Y   N     N
  5366.  
  5367.                           SIX    Y    Y    N    N   N     N
  5368.  
  5369.                           X      Y    N    N    N   N     N
  5370.                          ___________________________________
  5371.                          |
  5372.  
  5373.  
  5374.  
  5375.  
  5376.  
  5377.  
  5378.  
  5379.  
  5380.  
  5381.  
  5382.  
  5383.  
  5384.  
  5385.  
  5386.                                |
  5387.  
  5388.  
  5389.  
  5390.  
  5391.  
  5392.  
  5393.  
  5394.  
  5395.  
  5396.  
  5397.  
  5398.  
  5399.  
  5400.                                                             |
  5401.  
  5402.  
  5403.  
  5404.  
  5405.  
  5406.  
  5407.  
  5408.  
  5409.  
  5410.  
  5411.  
  5412.  
  5413.  
  5414.  
  5415.  
  5416.  
  5417.  
  5418.                            Table A.1: Lock Compatibility
  5419.  
  5420.  
  5421.  
  5422.  
  5423.  
  5424.                                          75
  5425.  
  5426.  
  5427.  
  5428.  
  5429.  
  5430.  
  5431.  
  5432.  
  5433.  
  5434.  
  5435.           Another table can be used to express lock convertibility. A  lock
  5436.           conversion  occurs  when  a  client holds a lock in some mode and
  5437.           requests an operation that requires  a  different  mode  for  the
  5438.           lock.  Table  A.2 is a lock convertibility table for the six file
  5439.           lock modes. Each row indicates a lock  that  the  client  already
  5440.           holds and each column indicates the new lock mode requested.  The
  5441.           entries represent the resulting lock mode obtained.
  5442.  
  5443.  
  5444.           A.2.  Locks Obtained by Operations
  5445.  
  5446.           The locks mentioned above are obtained on two types of structures
  5447.           in the Storage Manager: files and pages. Only the pages that con-
  5448.           tain object headers and root entries  are  locked;  large  object
  5449.           data  pages and file index pages are not locked.  The entire root
  5450.           entry page is locked when a root entry is used.
  5451.  
  5452.           Table A.3 lists all of the locks obtained by the various  Storage
  5453.           Manager  operations.   The  column labelled "File Lock" indicates
  5454.           what lock mode is used for locking the  file  in  question.   The
  5455.           column  labelled "Page Lock" indicates what lock mode is used for
  5456.           locking pages containing the objects or root entries in question.
  5457.           Locks  are  held  until  the end of the transaction in which they
  5458.           were acquired.
  5459.  
  5460.           Some applications may find it necessary to acquire more  restric-
  5461.           tive  locks  on  pages  and files to avoid conflicts during lock-
  5462.           upgrade requests. For example, consider an application that reads
  5463.  
  5464.  
  5465.                       ________________________________________
  5466.  
  5467.                        Lock           Lock Requested
  5468.                        Held   NL    IS    IX     S    SIX   X
  5469.                       ________________________________________
  5470.                        NL     NL    IS    IX    S     SIX   X
  5471.  
  5472.                        IS     IS    IS    IX    S     SIX   X
  5473.  
  5474.                        IX      IX   IX    IX    SIX   SIX   X
  5475.  
  5476.                        S       S    S     SIX   S     SIX   X
  5477.  
  5478.                        SIX    SIX   SIX   SIX   SIX   SIX   X
  5479.  
  5480.                        X      X     X     X     X     X     X
  5481.                       ________________________________________
  5482.                       |
  5483.  
  5484.  
  5485.  
  5486.  
  5487.  
  5488.  
  5489.  
  5490.  
  5491.  
  5492.  
  5493.  
  5494.  
  5495.  
  5496.  
  5497.                             |
  5498.  
  5499.  
  5500.  
  5501.  
  5502.  
  5503.  
  5504.  
  5505.  
  5506.  
  5507.  
  5508.  
  5509.  
  5510.  
  5511.                                                               |
  5512.  
  5513.  
  5514.  
  5515.  
  5516.  
  5517.  
  5518.  
  5519.  
  5520.  
  5521.  
  5522.  
  5523.  
  5524.  
  5525.  
  5526.  
  5527.  
  5528.  
  5529.                           Table A.2: Lock Convertibility
  5530.  
  5531.  
  5532.  
  5533.  
  5534.  
  5535.                                          76
  5536.  
  5537.  
  5538.  
  5539.  
  5540.  
  5541.  
  5542.  
  5543.  
  5544.  
  5545.  
  5546.           an object (with  sm_ReadObject( ))  and  subsequently  writes  it
  5547.           (with  sm_WriteObject( )).  When the object is read, a share lock
  5548.           is acquired for the object's page. When the object is written,  a
  5549.           lock-upgrade request is sent to the server to obtain an exclusive
  5550.           lock on the page.  This extra message is relatively expensive and
  5551.           can  lead  to potential deadlock if other clients are locking the
  5552.           page as well.  To avoid this problem, the "pagelock"  option  can
  5553.           be  used  to  change  the default lock modes used when the client
  5554.           library locks a page.  See Table 1 and the discussion  of  client
  5555.           options  in  Section  4.2, Initialization and Shutdown Operations
  5556.           for information about setting client options.  See Appendix A for
  5557.           more information about lock modes and the Storage Manager's lock-
  5558.           ing protocols.
  5559.  
  5560.  
  5561.           A.3.  Deadlock Detection and Avoidance
  5562.  
  5563.           With each lock request, a server  analyzes  its  local  waits-for
  5564.           graph  and  detects  local  cycles,  or  "local  deadlocks".  The
  5565.           request  that  would  cause  a  deadlock   is   denied   (returns
  5566.           esmFAILURE), and the client library returns esmLOCKCAUSEDDEADLOCK
  5567.           to the application in the global variable sm_errno.
  5568.  
  5569.           Distributed transactions may also cause a deadlock.  The  servers
  5570.           do  not  detect  deadlocks  that  involve  other servers.  Global
  5571.           deadlocks are avoided by timing out  locks.   Each  request  that
  5572.           awaits  a  lock  is aged.  When its age exceeds the time given by
  5573.           the client's "locktimeout" option, the request is denied (returns
  5574.           esmFAILURE),  and  the  client library returns esmLOCKBUSY to the
  5575.           application in the global variable sm_errno.
  5576.  
  5577.           When  an  application's  request  fails   with   esmLOCKBUSY   or
  5578.           esmLOCKCAUSEDDEADLOCK,  the  application  must abort its transac-
  5579.           tion, to free the locks it holds, and it must start its  transac-
  5580.           tion again.
  5581.  
  5582.  
  5583.  
  5584.  
  5585.  
  5586.  
  5587.  
  5588.  
  5589.  
  5590.  
  5591.  
  5592.  
  5593.  
  5594.  
  5595.  
  5596.  
  5597.  
  5598.  
  5599.  
  5600.  
  5601.                                          77
  5602.  
  5603.  
  5604.  
  5605.  
  5606.  
  5607.  
  5608.  
  5609.  
  5610.  
  5611.  
  5612.  
  5613.  
  5614.           ___________________________________________________________________
  5615.  
  5616.                   Operation          File Lock   Page Lock      Comments
  5617.           ___________________________________________________________________
  5618.            sm_Initialize( )          -           -           no locks needed
  5619.            sm_ShutDown( )            -           -           no locks needed
  5620.            sm_OpenBufferGroup( )     -           -           no locks needed
  5621.            sm_CloseBufferGroup( )    -           -           no locks needed
  5622.  
  5623.            sm_SetRootEntry( )        -           X           root entry page
  5624.            sm_GetRootEntry( )        -           S           root entry page
  5625.            sm_RemoveRootEntry( )     -           X           root entry page
  5626.  
  5627.            sm_CreateFile( )          X           -
  5628.            sm_DestroyFile( )         X           -
  5629.  
  5630.            sm_GetFirstOid( )         S           -
  5631.            sm_GetLastOid( )          S           -
  5632.            sm_GetNextOid( )          S           -
  5633.            sm_GetPreviousOid( )      S           -
  5634.  
  5635.            sm_OpenScan( )            S           -
  5636.            sm_OpenScanWithGroup( )   S           -
  5637.            sm_ScanNextObject( )      -           -           no locks needed
  5638.            sm_CloseScan( )           -           -           no locks needed
  5639.  
  5640.            sm_OpenLoad( )            X           -
  5641.            sm_LoadNextObject( )      -           -           no locks needed
  5642.            sm_CloseLoad( )           -           -           no locks needed
  5643.  
  5644.            sm_CreateObject( )        IX          X           unordered file
  5645.            sm_DestroyObject( )       IX          X
  5646.            sm_ReadObject( )          IS          S
  5647.            sm_ReadObjectHeader( )    IS          S
  5648.            sm_ReleaseObject( )       -           -           no locks needed
  5649.            sm_WriteObject( )         IX          X
  5650.            sm_InsertInObject( )      IX          X
  5651.            sm_AppendToObject( )      IX          X
  5652.            sm_DeleteFromObject( )    IX          X
  5653.  
  5654.            sm_CreateVersion( )       IX          X
  5655.            sm_FreezeVersion( )       IX          X
  5656.           ___________________________________________________________________
  5657.           |
  5658.  
  5659.  
  5660.  
  5661.  
  5662.  
  5663.  
  5664.  
  5665.  
  5666.  
  5667.  
  5668.  
  5669.  
  5670.  
  5671.  
  5672.  
  5673.  
  5674.  
  5675.  
  5676.  
  5677.  
  5678.  
  5679.  
  5680.  
  5681.  
  5682.  
  5683.  
  5684.  
  5685.  
  5686.  
  5687.  
  5688.  
  5689.  
  5690.  
  5691.  
  5692.  
  5693.  
  5694.  
  5695.  
  5696.  
  5697.  
  5698.                                                                              |
  5699.  
  5700.  
  5701.  
  5702.  
  5703.  
  5704.  
  5705.  
  5706.  
  5707.  
  5708.  
  5709.  
  5710.  
  5711.  
  5712.  
  5713.  
  5714.  
  5715.  
  5716.  
  5717.  
  5718.  
  5719.  
  5720.  
  5721.  
  5722.  
  5723.  
  5724.  
  5725.  
  5726.  
  5727.  
  5728.  
  5729.  
  5730.  
  5731.  
  5732.  
  5733.  
  5734.  
  5735.  
  5736.  
  5737.  
  5738.  
  5739.  
  5740.  
  5741.  
  5742.                       Table A.3: Locks Obtained by Operations
  5743.  
  5744.  
  5745.  
  5746.  
  5747.  
  5748.  
  5749.  
  5750.                                          78
  5751.  
  5752.  
  5753.  
  5754.  
  5755.  
  5756.  
  5757.  
  5758.  
  5759.  
  5760.  
  5761.           B.  APPENDIX : Generation of Unique Numbers for OIDs
  5762.  
  5763.           The "unique" field of an OID is special 32-bit value that is gen-
  5764.           erated  when  the  object is created and used to detect instances
  5765.           where the OID has become dangling or corrupted.  The values  that
  5766.           are  stored  in  "unique" fields are generated by Storage Manager
  5767.           servers. Disk volumes are partitioned into blocks  of  32  pages,
  5768.           and for each partition a 32-bit counter is maintained. When a new
  5769.           page is allocated, it is allotted a range (100) of unique numbers
  5770.           to  use during object creation. The counter in the partition con-
  5771.           taining the new page is incremented  to  reflect  the  allotment.
  5772.           When  this allotment has been exhausted, a request is made to the
  5773.           server for another allotment. When an object is created in a par-
  5774.           ticular  partition, the "unique" field of the new object's OID is
  5775.           set to the next available number in the range on the page.  While
  5776.           this  strategy  does  not  guarantee that OIDs are unique for all
  5777.           time, the probability of a dangling OID that  maps  to  the  same
  5778.           page  and  the   same  slot, and has the same "unique" field as a
  5779.           valid OID is very low.  As a result, "unique" fields can be  used
  5780.           virtually  to  guarantee  the validity of an OID. We adopted this
  5781.           approach instead of using unique-for-all-time logical OIDs with a
  5782.           surrogate  index in order to avoid the extra disk I/Os that might
  5783.           be needed to translate a logical OID to a physical address.
  5784.  
  5785.  
  5786.  
  5787.  
  5788.  
  5789.  
  5790.  
  5791.  
  5792.  
  5793.  
  5794.  
  5795.  
  5796.  
  5797.  
  5798.  
  5799.  
  5800.  
  5801.  
  5802.  
  5803.  
  5804.  
  5805.  
  5806.  
  5807.  
  5808.  
  5809.  
  5810.  
  5811.  
  5812.  
  5813.  
  5814.  
  5815.  
  5816.                                          79
  5817.  
  5818.  
  5819.  
  5820.  
  5821.  
  5822.  
  5823.  
  5824.  
  5825.  
  5826.  
  5827.  
  5828.  
  5829.  
  5830.  
  5831.  
  5832.  
  5833.  
  5834.  
  5835.  
  5836.  
  5837.  
  5838.  
  5839.  
  5840.  
  5841.  
  5842.  
  5843.  
  5844.  
  5845.  
  5846.  
  5847.  
  5848.  
  5849.  
  5850.  
  5851.  
  5852.  
  5853.  
  5854.  
  5855.  
  5856.  
  5857.  
  5858.  
  5859.  
  5860.  
  5861.  
  5862.  
  5863.  
  5864.  
  5865.  
  5866.  
  5867.  
  5868.  
  5869.  
  5870.  
  5871.  
  5872.  
  5873.  
  5874.  
  5875.  
  5876.  
  5877.  
  5878.  
  5879.  
  5880.  
  5881.  
  5882.                                          80
  5883.  
  5884.  
  5885.  
  5886.  
  5887.  
  5888.  
  5889.                                   TABLE OF CONTENTS
  5890.  
  5891.  
  5892.           1  INTRODUCTION ............................................    1
  5893.           2  OVERVIEW OF THE EXODUS STORAGE MANAGER ..................    1
  5894.                   2.1  Architecture ..................................    1
  5895.                   2.2  Facilities ....................................    2
  5896.                           2.2.1  Objects .............................    2
  5897.                           2.2.2  Versions ............................    3
  5898.                           2.2.3  Files ...............................    3
  5899.                           2.2.4  Indexes .............................    3
  5900.                           2.2.5  Volumes .............................    3
  5901.                           2.2.6  Transactions ........................    4
  5902.                           2.2.7  Concurrency Control .................    4
  5903.                           2.2.8  Recovery ............................    4
  5904.                           2.2.9  Configuration Options ...............    4
  5905.                   2.3  Illustration of Using the Storage Manager .....    4
  5906.                           2.3.1  Files Needed ........................    5
  5907.                           2.3.2  Preparing Your Disks ................    6
  5908.                           2.3.3  Configuring a Server ................    7
  5909.                           2.3.4    Compiling   and   Linking   Your
  5910.                Application ...........................................    8
  5911.                           2.3.5   Configuring  and   Running   Your
  5912.                Application ...........................................    8
  5913.                           2.3.6  Shutting Down the Server ............    9
  5914.           3  CONFIGURATION OPTIONS AND CONFIGURATION FILES ...........   11
  5915.           4  THE STORAGE MANAGER APPLICATION INTERFACE ...............   13
  5916.                   4.1  Handling Errors ...............................   13
  5917.                   4.2  Initialization and Shutdown Operations ........   15
  5918.                   4.3  Transactions ..................................   21
  5919.                           4.3.1  Transaction Identifiers .............   21
  5920.                           4.3.2  Transaction States ..................   22
  5921.                           4.3.3  Transaction Operations ..............   22
  5922.                   4.4  Mounting and Dismounting Volumes ..............   24
  5923.                   4.5  Root Entries ..................................   25
  5924.                   4.6  Buffer Operations .............................   26
  5925.                   4.7  Operations on Objects .........................   28
  5926.                           4.7.1  Creating and Destroying Objects .....   31
  5927.                           4.7.2  Pinning and Unpinning Objects .......   32
  5928.                           4.7.3  Modifying Objects ...................   33
  5929.                           4.7.4  Object Headers ......................   35
  5930.                   4.8  Versions of Objects ...........................   36
  5931.                   4.9  Operations on Files ...........................   37
  5932.                           4.9.1  Consistency Guarantees  for  Files
  5933.                .......................................................   38
  5934.                           4.9.2  Scanning Files ......................   40
  5935.                           4.9.3  Bulk-loading Files ..................   43
  5936.                   4.10  Operations on Indexes ........................   43
  5937.                           4.10.1  Creating and  Destroying  Indexes
  5938.                .......................................................   44
  5939.                           4.10.2   Inserting  and  Removing   Index
  5940.                Elements ..............................................   46
  5941.                           4.10.3  Loading Indexes in Bulk ............   46
  5942.                           4.10.4  Scanning Indexes ...................   47
  5943.                   4.11  Advanced Topics ..............................   49
  5944.                           4.11.1    External    Two-Phase    Commit
  5945.  
  5946.  
  5947.  
  5948.                                           i
  5949.  
  5950.  
  5951.  
  5952.  
  5953.  
  5954.  
  5955.  
  5956.  
  5957.  
  5958.  
  5959.                Functions .............................................   49
  5960.                           4.11.2  Administrative Operations ..........   53
  5961.                           4.11.3  Tuning the Application .............   57
  5962.           5  USING STORAGE MANAGER SERVERS ...........................   58
  5963.                   5.1  Managing Volumes ..............................   58
  5964.                           5.1.1  Log Volumes .........................   58
  5965.                           5.1.2  Data Volumes ........................   58
  5966.                           5.1.3  Temporary Volumes ...................   58
  5967.                           5.1.4  Raw Partitions and Unix Files .......   59
  5968.                           5.1.5  Formatting Volumes ..................   59
  5969.                           5.1.6  Size Requirements for Log  Volumes
  5970.                .......................................................   61
  5971.                           5.1.7  Backing Up Volumes ..................   62
  5972.                   5.2  Using the Server ..............................   63
  5973.                           5.2.1  Starting the Server .................   63
  5974.                           5.2.2  Configuring the Server ..............   64
  5975.                           5.2.3  Normal Operation of Servers .........   67
  5976.                                   5.2.3.1  Server Commands ...........   68
  5977.                           5.2.4  Shutting Down the Server ............   70
  5978.                                   5.2.4.1  Running  the  Shutserver
  5979.                program ...............................................   70
  5980.                           5.2.5  Recovery ............................   71
  5981.                   5.3  Tuning the Server .............................   71
  5982.                                   5.3.1.1  The Size of  the  Buffer
  5983.                Pool ..................................................   71
  5984.                                   5.3.1.2  The Size of Log Pages .....   72
  5985.                                   5.3.1.3  Checkpoint Frequency ......   72
  5986.           6  REFERENCES ..............................................   73
  5987.           A   APPENDIX  :  Locking  Protocol  for  Storage  Manager
  5988.                Operations ............................................   75
  5989.                   A.1  Lock Modes ....................................   75
  5990.                   A.2  Locks Obtained by Operations ..................   76
  5991.                   A.3  Deadlock Detection and Avoidance ..............   77
  5992.           B  APPENDIX : Generation of Unique Numbers for OIDs ........   79
  5993.  
  5994.  
  5995.  
  5996.  
  5997.  
  5998.  
  5999.  
  6000.  
  6001.  
  6002.  
  6003.  
  6004.  
  6005.  
  6006.  
  6007.  
  6008.  
  6009.  
  6010.  
  6011.  
  6012.  
  6013.  
  6014.                                          ii
  6015.  
  6016.  
  6017.  
  6018.